From 237d658e8fcc8a899d950444c36e809b85869dc1 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 11 Apr 2016 20:45:37 +0200 Subject: [PATCH 001/268] Code cleanup in OpenDatabaseAction --- .../jabref/importer/OpenDatabaseAction.java | 32 +++---------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index 66f673fb5358..db4975320340 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -103,23 +103,6 @@ public void actionPerformed(ActionEvent e) { openFiles(filesToOpen, true); } - class OpenItSwingHelper implements Runnable { - - private final BasePanel basePanel; - private final boolean raisePanel; - - OpenItSwingHelper(BasePanel basePanel, boolean raisePanel) { - this.basePanel = basePanel; - this.raisePanel = raisePanel; - } - - @Override - public void run() { - frame.addTab(basePanel, raisePanel); - - } - } - /** * Opens the given file. If null or 404, nothing happens * @@ -172,7 +155,7 @@ public void openFiles(List filesToOpen, boolean raisePanel) { // locking until the file is loaded. if (!filesToOpen.isEmpty()) { final List theFiles = Collections.unmodifiableList(filesToOpen); - JabRefExecutorService.INSTANCE.execute((Runnable) () -> { + JabRefExecutorService.INSTANCE.execute(() -> { for (File theFile : theFiles) { openTheFile(theFile, raisePanel); } @@ -294,13 +277,8 @@ private void openTheFile(File file, boolean raisePanel) { // if the database contents should be modified due to new features // in this version of JabRef: final ParserResult finalReferenceToResult = result; - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - OpenDatabaseAction.performPostOpenActions(panel, finalReferenceToResult, true); - } - }); + SwingUtilities.invokeLater( + () -> OpenDatabaseAction.performPostOpenActions(panel, finalReferenceToResult, true)); } } @@ -337,7 +315,7 @@ public BasePanel addNewDatabase(ParserResult result, final File file, boolean ra BasePanel basePanel = new BasePanel(frame, new BibDatabaseContext(database, meta, file, defaults), result.getEncoding()); // file is set to null inside the EventDispatcherThread - SwingUtilities.invokeLater(new OpenItSwingHelper(basePanel, raisePanel)); + SwingUtilities.invokeLater(() -> frame.addTab(basePanel, raisePanel)); frame.output(Localization.lang("Opened database") + " '" + fileName + "' " + Localization.lang("with") + " " + database.getEntryCount() + " " + Localization.lang("entries") + "."); @@ -355,7 +333,7 @@ public static ParserResult loadDatabase(File fileToOpen, Charset defaultEncoding // encoding in the first place. Since the signature doesn't contain any fancy characters, we can // read it regardless of encoding, with either UTF-8 or UTF-16. That's the hypothesis, at any rate. // 8 bit is most likely, so we try that first: - Optional suppliedEncoding = Optional.empty(); + Optional suppliedEncoding; try (Reader utf8Reader = ImportFormatReader.getUTF8Reader(fileToOpen)) { suppliedEncoding = OpenDatabaseAction.getSuppliedEncoding(utf8Reader); } From d5e298a7b75f9bb4f1bc8c1d96466be0247d1a6c Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 13 Apr 2016 21:37:00 +0200 Subject: [PATCH 002/268] Rework importer interface --- src/main/java/net/sf/jabref/Globals.java | 1 - src/main/java/net/sf/jabref/JabRef.java | 60 +++++-- .../jabref/exporter/CustomExportDialog.java | 3 +- .../jabref/exporter/SaveDatabaseAction.java | 35 ++-- .../external/ExternalFileTypeEntryEditor.java | 3 +- .../sf/jabref/external/MoveFileAction.java | 26 ++- .../java/net/sf/jabref/gui/BasePanel.java | 119 +++++++++---- .../java/net/sf/jabref/gui/FileDialogs.java | 65 ++++--- .../sf/jabref/gui/FileListEntryEditor.java | 53 ++++-- .../net/sf/jabref/gui/OpenFileFilter.java | 24 ++- .../sf/jabref/gui/actions/BrowseAction.java | 23 +-- .../jabref/gui/auximport/FromAuxDialog.java | 5 +- .../gui/journals/ManageJournalsPanel.java | 8 +- .../gui/plaintextimport/TextInputDialog.java | 100 +++++------ .../gui/preftabs/PreferencesDialog.java | 9 +- .../sf/jabref/importer/CustomImporter.java | 1 - .../importer/ImportCustomizationDialog.java | 25 +-- .../jabref/importer/ImportFormatReader.java | 97 ++++++----- .../sf/jabref/importer/ImportMenuItem.java | 24 ++- .../jabref/importer/OpenDatabaseAction.java | 3 +- .../net/sf/jabref/importer/ParserResult.java | 18 +- .../sf/jabref/importer/ZipFileChooser.java | 2 +- .../importer/fetcher/DOItoBibTeXFetcher.java | 39 ++--- .../importer/fetcher/MedlineFetcher.java | 24 ++- .../fileformat/BiblioscapeImporter.java | 34 ++-- .../importer/fileformat/BibteXMLImporter.java | 41 ++--- .../importer/fileformat/BibtexImporter.java | 32 ++-- .../importer/fileformat/CopacImporter.java | 39 ++--- .../importer/fileformat/EndnoteImporter.java | 33 ++-- .../importer/fileformat/FreeCiteImporter.java | 50 +++--- .../importer/fileformat/ImportFormat.java | 159 +++++++----------- .../importer/fileformat/InspecImporter.java | 42 ++--- .../importer/fileformat/IsiImporter.java | 42 ++--- .../importer/fileformat/MedlineImporter.java | 71 +++----- .../fileformat/MedlinePlainImporter.java | 40 ++--- .../importer/fileformat/MsBibImporter.java | 35 ++-- .../importer/fileformat/OvidImporter.java | 44 ++--- .../fileformat/PdfContentImporter.java | 83 ++++----- .../importer/fileformat/PdfXmpImporter.java | 35 ++-- .../importer/fileformat/RepecNepImporter.java | 47 ++---- .../importer/fileformat/RisImporter.java | 41 ++--- .../fileformat/SilverPlatterImporter.java | 39 ++--- ...=> ImportFormatReaderIntegrationTest.java} | 23 ++- .../ImportFormatReaderTestParameterless.java | 27 +-- .../fileformat/BiblioscapeImporterTest.java | 2 +- .../fileformat/BibtexImporterTest.java | 16 +- .../fileformat/EndnoteImporterTest.java | 2 +- .../importer/fileformat/ImportFormatTest.java | 105 ++++++++++++ .../importer/fileformat/InspecImportTest.java | 17 +- .../importer/fileformat/IsiImporterTest.java | 31 +--- .../fileformat/MedlinePlainImporterTest.java | 33 ++-- .../fileformat/MsBibImporterTest.java | 2 +- .../importer/fileformat/OvidImporterTest.java | 2 +- .../fileformat/PdfXmpImporterTest.java | 26 +-- .../importer/fileformat/RISImporterTest.java | 2 +- .../fileformat/RepecNepImporterTest.java | 19 +-- ...edlinePlainImporterTestMultipleEntries.txt | 4 +- 57 files changed, 1058 insertions(+), 927 deletions(-) rename src/test/java/net/sf/jabref/importer/{ImportFormatReaderTest.java => ImportFormatReaderIntegrationTest.java} (76%) create mode 100644 src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java diff --git a/src/main/java/net/sf/jabref/Globals.java b/src/main/java/net/sf/jabref/Globals.java index 78b9dce6034a..3db58a539a06 100644 --- a/src/main/java/net/sf/jabref/Globals.java +++ b/src/main/java/net/sf/jabref/Globals.java @@ -48,7 +48,6 @@ public class Globals { public static final String SELECTOR_META_PREFIX = "selector_"; public static final String PROTECTED_FLAG_META = "protectedFlag"; - public static final String NONE = "_non__"; public static final String SPECIAL_COMMAND_CHARS = "\"`^~'c="; diff --git a/src/main/java/net/sf/jabref/JabRef.java b/src/main/java/net/sf/jabref/JabRef.java index ee9a0126ac9f..cb35d3cf4fef 100644 --- a/src/main/java/net/sf/jabref/JabRef.java +++ b/src/main/java/net/sf/jabref/JabRef.java @@ -20,20 +20,47 @@ import java.io.IOException; import java.net.Authenticator; import java.nio.charset.Charset; -import java.util.*; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.Vector; import java.util.prefs.BackingStoreException; -import javax.swing.*; + +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; import javax.swing.plaf.FontUIResource; -import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; -import com.jgoodies.looks.plastic.theme.SkyBluer; import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.cli.AuxCommandLine; -import net.sf.jabref.exporter.*; -import net.sf.jabref.gui.*; +import net.sf.jabref.exporter.AutoSaveManager; +import net.sf.jabref.exporter.BibDatabaseWriter; +import net.sf.jabref.exporter.ExportFormats; +import net.sf.jabref.exporter.IExportFormat; +import net.sf.jabref.exporter.SaveException; +import net.sf.jabref.exporter.SavePreferences; +import net.sf.jabref.exporter.SaveSession; +import net.sf.jabref.gui.BasePanel; +import net.sf.jabref.gui.GUIGlobals; +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.ParserResultWarningDialog; import net.sf.jabref.gui.remote.JabRefMessageHandler; import net.sf.jabref.gui.util.FocusRequester; -import net.sf.jabref.importer.*; +import net.sf.jabref.importer.AutosaveStartupPrompter; +import net.sf.jabref.importer.ImportFormatReader; +import net.sf.jabref.importer.ImportInspectionCommandLine; +import net.sf.jabref.importer.OpenDatabaseAction; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fetcher.EntryFetcher; import net.sf.jabref.importer.fetcher.EntryFetchers; import net.sf.jabref.logic.CustomEntryTypesManager; @@ -57,6 +84,9 @@ import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.util.Util; + +import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; +import com.jgoodies.looks.plastic.theme.SkyBluer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -802,14 +832,20 @@ private static Optional importFile(String argument) { if ((data.length > 1) && !"*".equals(data[1])) { System.out.println(Localization.lang("Importing") + ": " + data[0]); try { - List entries; + ParserResult parserResult; if (OS.WINDOWS) { - entries = Globals.IMPORT_FORMAT_READER.importFromFile(data[1], data[0], JabRef.mainFrame); + Path file = Paths.get(data[0]); + parserResult = Globals.IMPORT_FORMAT_READER.importFromFile(data[1], file); } else { - entries = Globals.IMPORT_FORMAT_READER.importFromFile(data[1], - data[0].replace("~", System.getProperty("user.home")), JabRef.mainFrame); + Path file = Paths.get(data[0].replace("~", System.getProperty("user.home"))); + parserResult = Globals.IMPORT_FORMAT_READER.importFromFile(data[1], file); + } + + if(parserResult.hasWarnings()) { + mainFrame.showMessage(parserResult.getErrorMessage()); } - return Optional.of(new ParserResult(entries)); + + return Optional.of(parserResult); } catch (IllegalArgumentException ex) { System.err.println(Localization.lang("Unknown import format") + ": " + data[1]); return Optional.empty(); diff --git a/src/main/java/net/sf/jabref/exporter/CustomExportDialog.java b/src/main/java/net/sf/jabref/exporter/CustomExportDialog.java index 454b3f0b0b1d..95fc0c7b1630 100644 --- a/src/main/java/net/sf/jabref/exporter/CustomExportDialog.java +++ b/src/main/java/net/sf/jabref/exporter/CustomExportDialog.java @@ -22,6 +22,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.util.Collections; import javax.swing.*; @@ -93,7 +94,7 @@ public void actionPerformed(ActionEvent e) { JButton browse = new JButton(Localization.lang("Browse")); browse.addActionListener(e -> { File directory = new File(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY)); - String chosenStr = FileDialogs.getNewFile(parent, directory, ".layout", + String chosenStr = FileDialogs.getNewFile(parent, directory, Collections.singletonList(".layout"), JFileChooser.OPEN_DIALOG, false); if (chosenStr == null) { return; diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java index 9f6231a93e54..cfaea741e27b 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java @@ -15,30 +15,37 @@ */ package net.sf.jabref.exporter; -import com.jgoodies.forms.builder.FormBuilder; -import com.jgoodies.forms.layout.FormLayout; -import net.sf.jabref.*; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.Collections; +import java.util.List; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefExecutorService; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.collab.ChangeScanner; import net.sf.jabref.gui.BasePanel; +import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.worker.AbstractWorker; -import net.sf.jabref.gui.FileDialogs; -import net.sf.jabref.collab.ChangeScanner; import net.sf.jabref.gui.worker.CallBack; import net.sf.jabref.gui.worker.Worker; import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileBasedLock; -import javax.swing.*; +import com.jgoodies.forms.builder.FormBuilder; +import com.jgoodies.forms.layout.FormLayout; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; -import java.util.List; - /** * Action for the "Save" and "Save as" operations called from BasePanel. This class is also used for * save operations when closing a database or quitting the applications. @@ -343,8 +350,8 @@ public void saveAs() throws Throwable { String chosenFile = null; File f = null; while (f == null) { - chosenFile = FileDialogs.getNewFile(frame, new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), ".bib", - JFileChooser.SAVE_DIALOG, false, null); + chosenFile = FileDialogs.getNewFile(frame, new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), + Collections.singletonList(".bib"), JFileChooser.SAVE_DIALOG, false, null); if (chosenFile == null) { cancelled = true; return; // cancelled diff --git a/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java b/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java index 1c590feaa48d..53a08908f7e1 100644 --- a/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java +++ b/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java @@ -20,6 +20,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.util.Collections; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -254,7 +255,7 @@ public void actionPerformed(ActionEvent e) { // Nothing in the field. Go to the last file dir used: initial = new File(Globals.prefs.get(JabRefPreferences.FILE_WORKING_DIRECTORY)); } - String chosen = FileDialogs.getNewFile(null, initial, Globals.NONE, + String chosen = FileDialogs.getNewFile(null, initial, Collections.emptyList(), JFileChooser.OPEN_DIALOG, false); if (chosen != null) { File newFile = new File(chosen); diff --git a/src/main/java/net/sf/jabref/external/MoveFileAction.java b/src/main/java/net/sf/jabref/external/MoveFileAction.java index 5a40cc2fcf4b..cfa84a86e5e6 100644 --- a/src/main/java/net/sf/jabref/external/MoveFileAction.java +++ b/src/main/java/net/sf/jabref/external/MoveFileAction.java @@ -15,25 +15,32 @@ */ package net.sf.jabref.external; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; + import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.*; +import net.sf.jabref.gui.FileDialogs; +import net.sf.jabref.gui.FileListEntry; +import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.entryeditor.EntryEditor; import net.sf.jabref.gui.fieldeditors.FileListEditor; import net.sf.jabref.gui.util.component.CheckBoxMessage; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.util.Util; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Locale; - /** * Action for moving or renaming a file that is linked to from an entry in JabRef. */ @@ -136,7 +143,8 @@ public void actionPerformed(ActionEvent event) { } chosenFile = sb.toString(); } else { - chosenFile = FileDialogs.getNewFile(frame, file, extension, JFileChooser.SAVE_DIALOG, false); + chosenFile = FileDialogs.getNewFile(frame, file, Collections.singletonList(extension), + JFileChooser.SAVE_DIALOG, false); } if (chosenFile == null) { return; // cancelled diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 6e6837e94d0c..54ab9320004a 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -15,15 +15,67 @@ */ package net.sf.jabref.gui; -import ca.odell.glazedlists.event.ListEventListener; -import com.jgoodies.forms.builder.FormBuilder; -import com.jgoodies.forms.layout.FormLayout; -import net.sf.jabref.*; +import java.awt.BorderLayout; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.event.ActionEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.tree.TreePath; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; + +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Globals; +import net.sf.jabref.HighlightMatchingGroupPreferences; +import net.sf.jabref.JabRefExecutorService; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.collab.ChangeScanner; import net.sf.jabref.collab.FileUpdateListener; import net.sf.jabref.collab.FileUpdatePanel; -import net.sf.jabref.exporter.*; -import net.sf.jabref.external.*; +import net.sf.jabref.exporter.BibDatabaseWriter; +import net.sf.jabref.exporter.ExportToClipboardAction; +import net.sf.jabref.exporter.SaveDatabaseAction; +import net.sf.jabref.exporter.SaveException; +import net.sf.jabref.exporter.SavePreferences; +import net.sf.jabref.exporter.SaveSession; +import net.sf.jabref.external.AttachFileAction; +import net.sf.jabref.external.ExternalFileMenuItem; +import net.sf.jabref.external.ExternalFileType; +import net.sf.jabref.external.ExternalFileTypes; +import net.sf.jabref.external.FindFullTextAction; +import net.sf.jabref.external.RegExpFileSearch; +import net.sf.jabref.external.SynchronizeFileField; +import net.sf.jabref.external.WriteXMPAction; import net.sf.jabref.groups.GroupSelector; import net.sf.jabref.groups.GroupTreeNode; import net.sf.jabref.gui.actions.Actions; @@ -43,10 +95,20 @@ import net.sf.jabref.gui.mergeentries.MergeEntryDOIDialog; import net.sf.jabref.gui.plaintextimport.TextInputDialog; import net.sf.jabref.gui.search.SearchBar; -import net.sf.jabref.gui.undo.*; +import net.sf.jabref.gui.undo.CountingUndoManager; +import net.sf.jabref.gui.undo.NamedCompound; +import net.sf.jabref.gui.undo.UndoableChangeType; +import net.sf.jabref.gui.undo.UndoableFieldChange; +import net.sf.jabref.gui.undo.UndoableInsertEntry; +import net.sf.jabref.gui.undo.UndoableKeyChange; +import net.sf.jabref.gui.undo.UndoableRemoveEntry; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.gui.util.component.CheckBoxMessage; -import net.sf.jabref.gui.worker.*; +import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.gui.worker.CallBack; +import net.sf.jabref.gui.worker.MarkEntriesAction; +import net.sf.jabref.gui.worker.SendAsEMailAction; +import net.sf.jabref.gui.worker.Worker; import net.sf.jabref.importer.AppendDatabaseAction; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.FieldChange; @@ -70,29 +132,28 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.IdGenerator; -import net.sf.jabref.specialfields.*; -import net.sf.jabref.sql.*; +import net.sf.jabref.specialfields.Printed; +import net.sf.jabref.specialfields.Priority; +import net.sf.jabref.specialfields.Quality; +import net.sf.jabref.specialfields.Rank; +import net.sf.jabref.specialfields.ReadStatus; +import net.sf.jabref.specialfields.Relevance; +import net.sf.jabref.specialfields.SpecialFieldAction; +import net.sf.jabref.specialfields.SpecialFieldDatabaseChangeListener; +import net.sf.jabref.specialfields.SpecialFieldValue; +import net.sf.jabref.sql.DBConnectDialog; +import net.sf.jabref.sql.DBExporterAndImporterFactory; +import net.sf.jabref.sql.DBStrings; +import net.sf.jabref.sql.DbConnectAction; +import net.sf.jabref.sql.SQLUtil; import net.sf.jabref.sql.exporter.DBExporter; + +import ca.odell.glazedlists.event.ListEventListener; +import com.jgoodies.forms.builder.FormBuilder; +import com.jgoodies.forms.layout.FormLayout; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import javax.swing.*; -import javax.swing.tree.TreePath; -import javax.swing.undo.CannotRedoException; -import javax.swing.undo.CannotUndoException; -import java.awt.*; -import java.awt.datatransfer.*; -import java.awt.event.ActionEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.io.File; -import java.io.IOException; -import java.io.StringReader; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; -import java.util.*; -import java.util.List; - public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListener { private static final Log LOGGER = LogFactory.getLog(BasePanel.class); @@ -2287,8 +2348,8 @@ public SaveSelectedAction(SavePreferences.DatabaseSaveType saveType) { public void action() throws SaveException { String chosenFile = FileDialogs.getNewFile(frame, - new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), ".bib", JFileChooser.SAVE_DIALOG, - false); + new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), Collections.singletonList(".bib"), + JFileChooser.SAVE_DIALOG, false); if (chosenFile != null) { File expFile = new File(chosenFile); if (!expFile.exists() || (JOptionPane.showConfirmDialog(frame, diff --git a/src/main/java/net/sf/jabref/gui/FileDialogs.java b/src/main/java/net/sf/jabref/gui/FileDialogs.java index a921dab8cb9a..fb5fe46b60a9 100644 --- a/src/main/java/net/sf/jabref/gui/FileDialogs.java +++ b/src/main/java/net/sf/jabref/gui/FileDialogs.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import javax.swing.JComponent; import javax.swing.JFileChooser; @@ -28,13 +29,6 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.util.OS; -/** - * Created by IntelliJ IDEA. - * User: alver - * Date: Apr 14, 2009 - * Time: 7:24:07 PM - * To change this template use File | Settings | File Templates. - */ public class FileDialogs { /** @@ -45,21 +39,24 @@ public class FileDialogs { * * @param owner * @param directory - * @param extension + * @param extensions * @param updateWorkingdirectory * @return an array of selected file paths, or an empty array if no selection is made. */ - public static List getMultipleFiles(JFrame owner, File directory, String extension, + public static List getMultipleFiles(JFrame owner, File directory, List extensions, boolean updateWorkingdirectory) { - OpenFileFilter off = null; - if (extension == null) { + Objects.requireNonNull(extensions); + + OpenFileFilter off; + if (extensions.isEmpty()) { off = new OpenFileFilter(); - } else if (!extension.equals(Globals.NONE)) { - off = new OpenFileFilter(extension); + } else { + off = new OpenFileFilter(extensions); } - Object files = FileDialogs.getNewFileImpl(owner, directory, extension, null, off, JFileChooser.OPEN_DIALOG, updateWorkingdirectory, false, true, null); + Object files = FileDialogs.getNewFileImpl(owner, directory, extensions, null, off, JFileChooser.OPEN_DIALOG, + updateWorkingdirectory, false, true, null); if (files instanceof String[]) { return Arrays.asList((String[]) files); @@ -72,40 +69,42 @@ public static List getMultipleFiles(JFrame owner, File directory, String return Collections.emptyList(); } - public static String getNewFile(JFrame owner, File directory, String extension, int dialogType, boolean updateWorkingDirectory) { - return FileDialogs.getNewFile(owner, directory, extension, null, dialogType, updateWorkingDirectory, false, null); + public static String getNewFile(JFrame owner, File directory, List extensions, int dialogType, boolean updateWorkingDirectory) { + return FileDialogs.getNewFile(owner, directory, extensions, null, dialogType, updateWorkingDirectory, false, null); } - public static String getNewFile(JFrame owner, File directory, String extension, int dialogType, boolean updateWorkingDirectory, JComponent accessory) { - return FileDialogs.getNewFile(owner, directory, extension, null, dialogType, updateWorkingDirectory, false, accessory); + public static String getNewFile(JFrame owner, File directory, List extensions, int dialogType, boolean updateWorkingDirectory, JComponent accessory) { + return FileDialogs.getNewFile(owner, directory, extensions, null, dialogType, updateWorkingDirectory, false, accessory); } - public static String getNewFile(JFrame owner, File directory, String extension, String description, int dialogType, boolean updateWorkingDirectory) { - return FileDialogs.getNewFile(owner, directory, extension, description, dialogType, updateWorkingDirectory, false, null); + public static String getNewFile(JFrame owner, File directory, List extensions, String description, int dialogType, boolean updateWorkingDirectory) { + return FileDialogs.getNewFile(owner, directory, extensions, description, dialogType, updateWorkingDirectory, false, null); } - public static String getNewDir(JFrame owner, File directory, String extension, int dialogType, boolean updateWorkingDirectory) { - return FileDialogs.getNewFile(owner, directory, extension, null, dialogType, updateWorkingDirectory, true, null); + public static String getNewDir(JFrame owner, File directory, List extensions, int dialogType, boolean updateWorkingDirectory) { + return FileDialogs.getNewFile(owner, directory, extensions, null, dialogType, updateWorkingDirectory, true, null); } - public static String getNewDir(JFrame owner, File directory, String extension, String description, int dialogType, boolean updateWorkingDirectory) { - return FileDialogs.getNewFile(owner, directory, extension, description, dialogType, updateWorkingDirectory, true, null); + public static String getNewDir(JFrame owner, File directory, List extensions, String description, int dialogType, boolean updateWorkingDirectory) { + return FileDialogs.getNewFile(owner, directory, extensions, description, dialogType, updateWorkingDirectory, true, null); } - private static String getNewFile(JFrame owner, File directory, String extension, String description, int dialogType, boolean updateWorkingDirectory, boolean dirOnly, JComponent accessory) { + private static String getNewFile(JFrame owner, File directory, List extensions, String description, int dialogType, boolean updateWorkingDirectory, boolean dirOnly, JComponent accessory) { - OpenFileFilter off = null; + OpenFileFilter off; - if (extension == null) { + if (extensions.isEmpty()) { off = new OpenFileFilter(); - } else if (!extension.equals(Globals.NONE)) { - off = new OpenFileFilter(extension); + } else { + off = new OpenFileFilter(extensions); } - return (String) FileDialogs.getNewFileImpl(owner, directory, extension, description, off, dialogType, updateWorkingDirectory, dirOnly, false, accessory); + return (String) FileDialogs.getNewFileImpl(owner, directory, extensions, description, off, dialogType, updateWorkingDirectory, dirOnly, false, accessory); } - private static Object getNewFileImpl(JFrame owner, File directory, String extension, String description, OpenFileFilter off, int dialogType, boolean updateWorkingDirectory, boolean dirOnly, boolean multipleSelection, JComponent accessory) { + private static Object getNewFileImpl(JFrame owner, File directory, List extensions, String description, + OpenFileFilter off, int dialogType, boolean updateWorkingDirectory, boolean dirOnly, + boolean multipleSelection, JComponent accessory) { // Added the !dirOnly condition below as a workaround to the native file dialog // not supporting directory selection: @@ -160,10 +159,10 @@ private static Object getNewFileImpl(JFrame owner, File directory, String extens // If this is a save dialog, and the user has not chosen "All files" as // filter // we enforce the given extension. But only if extension is not null. - if ((extension != null) && (dialogType == JFileChooser.SAVE_DIALOG) && (fc.getFileFilter() == off) && !off.accept(selectedFile)) { + if ((!extensions.isEmpty()) && (dialogType == JFileChooser.SAVE_DIALOG) && (fc.getFileFilter() == off) && !off.accept(selectedFile)) { // add the first extension if there are multiple extensions - selectedFile = new File(selectedFile.getPath() + extension.split("[, ]+", 0)[0]); + selectedFile = new File(selectedFile.getPath() + extensions.get(0)); } if (updateWorkingDirectory) { diff --git a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java index e51c1356a417..a48c47333cd9 100644 --- a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java @@ -15,9 +15,38 @@ */ package net.sf.jabref.gui; -import com.jgoodies.forms.builder.ButtonBarBuilder; -import com.jgoodies.forms.builder.FormBuilder; -import com.jgoodies.forms.layout.FormLayout; +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.regex.Pattern; + +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JProgressBar; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; @@ -29,21 +58,13 @@ import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; + +import com.jgoodies.forms.builder.ButtonBarBuilder; +import com.jgoodies.forms.builder.FormBuilder; +import com.jgoodies.forms.layout.FormLayout; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; -import java.awt.event.*; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.regex.Pattern; - /** * This class produces a dialog box for editing a single file link from a Bibtex entry. * @@ -343,7 +364,7 @@ public void actionPerformed(ActionEvent e) { // Nothing in the field. Go to the last file dir used: initial = new File(Globals.prefs.get(JabRefPreferences.FILE_WORKING_DIRECTORY)); } - String chosen = FileDialogs.getNewFile(parent, initial, Globals.NONE, + String chosen = FileDialogs.getNewFile(parent, initial, Collections.emptyList(), JFileChooser.OPEN_DIALOG, false); if (chosen != null) { File newFile = new File(chosen); diff --git a/src/main/java/net/sf/jabref/gui/OpenFileFilter.java b/src/main/java/net/sf/jabref/gui/OpenFileFilter.java index e499969fff17..c5a8fbb9150c 100644 --- a/src/main/java/net/sf/jabref/gui/OpenFileFilter.java +++ b/src/main/java/net/sf/jabref/gui/OpenFileFilter.java @@ -17,7 +17,9 @@ import java.io.File; import java.io.FilenameFilter; +import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; public class OpenFileFilter extends javax.swing.filechooser.FileFilter implements FilenameFilter { @@ -26,42 +28,38 @@ public class OpenFileFilter extends javax.swing.filechooser.FileFilter implement private final String desc; - public OpenFileFilter(String[] extensions) { + public OpenFileFilter(List extensions) { StringBuilder buf = new StringBuilder(); - int numExt = extensions.length; + int numExt = extensions.size(); if (numExt > 0) { buf.append('*'); - buf.append(extensions[0]); + buf.append(extensions.get(0)); - extSet.add(extensions[0]); + extSet.add(extensions.get(0)); } for (int curExt = 1; curExt < numExt; curExt++) { buf.append(", *"); - buf.append(extensions[curExt]); + buf.append(extensions.get(curExt)); - extSet.add(extensions[curExt]); + extSet.add(extensions.get(curExt)); } desc = buf.toString(); } public OpenFileFilter() { - this(new String[] { + this(Arrays.asList( ".bib", ".dat", // silverplatter ending - ".txt", // windows puts ".txt" extentions and for scifinder + ".txt", // windows puts ".txt" extensions and for scifinder ".ris", ".ref", // refer/endnote format ".fcgi", // default for pubmed ".bibx", // default for BibTeXML ".xml" - }); - } - - public OpenFileFilter(String s) { - this(s.split("[, ]+", 0)); + )); } @Override diff --git a/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java b/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java index 14d628819f2d..94a1eaa14320 100644 --- a/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java @@ -15,15 +15,19 @@ */ package net.sf.jabref.gui.actions; -import net.sf.jabref.Globals; -import net.sf.jabref.gui.FileDialogs; -import net.sf.jabref.gui.util.FocusRequester; -import net.sf.jabref.logic.l10n.Localization; - -import javax.swing.*; import java.awt.event.ActionEvent; import java.io.File; +import java.util.Collections; + +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JTextField; +import net.sf.jabref.gui.FileDialogs; +import net.sf.jabref.gui.util.FocusRequester; +import net.sf.jabref.logic.l10n.Localization; /** * Action used to produce a "Browse" button for one of the text fields. @@ -74,15 +78,14 @@ public void actionPerformed(ActionEvent e) { } } } - + private String askUser() { if (dir) { - return FileDialogs.getNewDir(frame, new File(comp.getText()), Globals.NONE, + return FileDialogs.getNewDir(frame, new File(comp.getText()), Collections.emptyList(), JFileChooser.OPEN_DIALOG, false); } else { - return FileDialogs.getNewFile(frame, new File(comp.getText()), Globals.NONE, + return FileDialogs.getNewFile(frame, new File(comp.getText()), Collections.emptyList(), JFileChooser.OPEN_DIALOG, false); } } - } diff --git a/src/main/java/net/sf/jabref/gui/auximport/FromAuxDialog.java b/src/main/java/net/sf/jabref/gui/auximport/FromAuxDialog.java index bd0597896038..bfc699689bfc 100644 --- a/src/main/java/net/sf/jabref/gui/auximport/FromAuxDialog.java +++ b/src/main/java/net/sf/jabref/gui/auximport/FromAuxDialog.java @@ -39,6 +39,7 @@ import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.io.File; +import java.util.Collections; import javax.swing.AbstractAction; import javax.swing.ActionMap; @@ -264,9 +265,7 @@ public BrowseAction(JTextField tc, JabRefFrame frame) { @Override public void actionPerformed(ActionEvent e) { - String chosen = FileDialogs.getNewFile(frame, - new File(comp.getText()), - ".aux", + String chosen = FileDialogs.getNewFile(frame, new File(comp.getText()), Collections.singletonList(".aux"), JFileChooser.OPEN_DIALOG, false); if (chosen != null) { File newFile = new File(chosen); diff --git a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java index e7ddb080db66..3e3a71df715f 100644 --- a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java +++ b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java @@ -439,11 +439,11 @@ public BrowseAction(JTextField tc, boolean dir) { public void actionPerformed(ActionEvent e) { String chosen; if (dir) { - chosen = FileDialogs.getNewDir(frame, new File(comp.getText()), Globals.NONE, JFileChooser.OPEN_DIALOG, - false); + chosen = FileDialogs.getNewDir(frame, new File(comp.getText()), Collections.emptyList(), + JFileChooser.OPEN_DIALOG, false); } else { - chosen = FileDialogs.getNewFile(frame, new File(comp.getText()), Globals.NONE, JFileChooser.OPEN_DIALOG, - false); + chosen = FileDialogs.getNewFile(frame, new File(comp.getText()), Collections.emptyList(), + JFileChooser.OPEN_DIALOG, false); } if (chosen != null) { File nFile = new File(chosen); diff --git a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java index f80865a334d9..a0909c144b8a 100644 --- a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java +++ b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java @@ -51,29 +51,28 @@ package net.sf.jabref.gui.plaintextimport; -import com.jgoodies.forms.builder.ButtonBarBuilder; - -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; -import net.sf.jabref.model.EntryTypes; -import net.sf.jabref.exporter.LatexFieldFormatter; -import net.sf.jabref.gui.ClipBoardManager; -import net.sf.jabref.gui.EntryMarker; -import net.sf.jabref.gui.FileDialogs; -import net.sf.jabref.gui.IconTheme; -import net.sf.jabref.gui.JabRefFrame; -import net.sf.jabref.gui.OSXCompatibleToolbar; -import net.sf.jabref.gui.keyboard.KeyBinding; -import net.sf.jabref.gui.undo.NamedCompound; -import net.sf.jabref.gui.util.component.OverlayPanel; -import net.sf.jabref.importer.fileformat.FreeCiteImporter; -import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.logic.util.UpdateField; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.EntryType; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import javax.swing.AbstractAction; import javax.swing.Action; @@ -110,32 +109,33 @@ import javax.swing.text.StyleContext; import javax.swing.text.StyledDocument; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.bibtex.BibEntryWriter; +import net.sf.jabref.bibtex.FieldProperties; +import net.sf.jabref.bibtex.InternalBibtexFields; +import net.sf.jabref.exporter.LatexFieldFormatter; +import net.sf.jabref.gui.ClipBoardManager; +import net.sf.jabref.gui.EntryMarker; +import net.sf.jabref.gui.FileDialogs; +import net.sf.jabref.gui.IconTheme; +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.OSXCompatibleToolbar; +import net.sf.jabref.gui.keyboard.KeyBinding; +import net.sf.jabref.gui.undo.NamedCompound; +import net.sf.jabref.gui.util.component.OverlayPanel; +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.importer.fileformat.FreeCiteImporter; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.UpdateField; +import net.sf.jabref.model.EntryTypes; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.EntryType; + +import com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; - public class TextInputDialog extends JDialog { private static final Log LOGGER = LogFactory.getLog(TextInputDialog.class); @@ -511,8 +511,12 @@ private boolean parseWithFreeCiteAndAddEntries() { text = text.replace(Globals.NEWLINE, " "); text = text.replace("##NEWLINE##", Globals.NEWLINE); - List importedEntries = fimp.importEntries(text, frame); - if (importedEntries == null) { + ParserResult importerResult = fimp.importEntries(text); + if(importerResult.hasWarnings()) { + frame.showMessage(importerResult.getErrorMessage()); + } + List importedEntries = importerResult.getDatabase().getEntries(); + if (importedEntries.isEmpty()) { return false; } else { UpdateField.setAutomaticFields(importedEntries, false, false); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java index 7e2d9a8958a0..f6ad87476f5f 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java @@ -19,6 +19,7 @@ import java.awt.event.ActionEvent; import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.prefs.BackingStoreException; @@ -158,8 +159,8 @@ public PreferencesDialog(JabRefFrame parent, JabRef jabRef) { // Import and export actions: exportPreferences.setToolTipText(Localization.lang("Export preferences to file")); exportPreferences.addActionListener(e -> { - String filename = FileDialogs.getNewFile(frame, new File(System.getProperty("user.home")), ".xml", - JFileChooser.SAVE_DIALOG, false); + String filename = FileDialogs.getNewFile(frame, new File(System.getProperty("user.home")), + Collections.singletonList(".xml"), JFileChooser.SAVE_DIALOG, false); if (filename == null) { return; } @@ -180,8 +181,8 @@ public PreferencesDialog(JabRefFrame parent, JabRef jabRef) { importPreferences.setToolTipText(Localization.lang("Import preferences from file")); importPreferences.addActionListener(e -> { - String filename = FileDialogs.getNewFile(frame, new File(System.getProperty("user.home")), ".xml", - JFileChooser.OPEN_DIALOG, false); + String filename = FileDialogs.getNewFile(frame, new File(System.getProperty("user.home")), + Collections.singletonList(".xml"), JFileChooser.OPEN_DIALOG, false); if (filename != null) { try { prefs.importPreferences(filename); diff --git a/src/main/java/net/sf/jabref/importer/CustomImporter.java b/src/main/java/net/sf/jabref/importer/CustomImporter.java index 9347fa7a0ee9..5c9c4de27851 100644 --- a/src/main/java/net/sf/jabref/importer/CustomImporter.java +++ b/src/main/java/net/sf/jabref/importer/CustomImporter.java @@ -136,7 +136,6 @@ public ImportFormat getInstance() throws IOException, MalformedURLException, Cla try (URLClassLoader cl = new URLClassLoader(new URL[] {getBasePathUrl()})) { Class clazz = Class.forName(className, true, cl); ImportFormat importFormat = (ImportFormat) clazz.newInstance(); - importFormat.setIsCustomImporter(true); return importFormat; } } diff --git a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java index f203543ec98a..8ff4782c9d6e 100644 --- a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java @@ -22,6 +22,8 @@ import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; import java.util.zip.ZipFile; import javax.swing.*; @@ -54,8 +56,7 @@ public class ImportCustomizationDialog extends JDialog { /** * - * @param frame_ - * @throws HeadlessException + * @param frame */ public ImportCustomizationDialog(final JabRefFrame frame) { super(frame, Localization.lang("Manage custom imports"), false); @@ -77,20 +78,22 @@ public ImportCustomizationDialog(final JabRefFrame frame) { JButton addFromFolderButton = new JButton(Localization.lang("Add from folder")); addFromFolderButton.addActionListener(e -> { - String chosenFileStr = null; CustomImporter importer = new CustomImporter(); - importer.setBasePath( - FileDialogs.getNewDir(frame, new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), - "", Localization.lang("Select Classpath of New Importer"), JFileChooser.CUSTOM_DIALOG, false)); + importer.setBasePath(FileDialogs + .getNewDir(frame, new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), + Collections.emptyList(), Localization.lang("Select Classpath of New Importer"), + JFileChooser.CUSTOM_DIALOG, false)); + String chosenFileStr = null; if (importer.getBasePath() != null) { - chosenFileStr = FileDialogs.getNewFile(frame, importer.getFileFromBasePath(), ".class", - Localization.lang("Select new ImportFormat Subclass"), JFileChooser.CUSTOM_DIALOG, false); + chosenFileStr = FileDialogs.getNewFile(frame, importer.getFileFromBasePath(), + Collections.singletonList(".class"), Localization.lang("Select new ImportFormat Subclass"), + JFileChooser.CUSTOM_DIALOG, false); } if (chosenFileStr != null) { try { importer.setClassName(pathToClass(importer.getFileFromBasePath(), new File(chosenFileStr))); importer.setName(importer.getInstance().getFormatName()); - importer.setCliId(importer.getInstance().getCLIId()); + importer.setCliId(importer.getInstance().getId()); addOrReplaceImporter(importer); customImporterTable.revalidate(); customImporterTable.repaint(); @@ -108,8 +111,8 @@ public ImportCustomizationDialog(final JabRefFrame frame) { JButton addFromJarButton = new JButton(Localization.lang("Add from jar")); addFromJarButton.addActionListener(e -> { String basePath = FileDialogs.getNewFile(frame, - new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), - ".zip,.jar", Localization.lang("Select a Zip-archive"), JFileChooser.CUSTOM_DIALOG, false); + new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), Arrays.asList(".zip", ".jar"), + Localization.lang("Select a Zip-archive"), JFileChooser.CUSTOM_DIALOG, false); if (basePath != null) { try (ZipFile zipFile = new ZipFile(new File(basePath), ZipFile.OPEN_READ)) { diff --git a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java index ffec4c726125..ef5336cdbf65 100644 --- a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java +++ b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java @@ -15,25 +15,54 @@ */ package net.sf.jabref.importer; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.*; - -import net.sf.jabref.importer.fileformat.*; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.SortedSet; +import java.util.TreeSet; + +import net.sf.jabref.Globals; +import net.sf.jabref.importer.fileformat.BiblioscapeImporter; +import net.sf.jabref.importer.fileformat.BibteXMLImporter; +import net.sf.jabref.importer.fileformat.BibtexImporter; +import net.sf.jabref.importer.fileformat.CopacImporter; +import net.sf.jabref.importer.fileformat.EndnoteImporter; +import net.sf.jabref.importer.fileformat.FreeCiteImporter; +import net.sf.jabref.importer.fileformat.ImportFormat; +import net.sf.jabref.importer.fileformat.InspecImporter; +import net.sf.jabref.importer.fileformat.IsiImporter; +import net.sf.jabref.importer.fileformat.MedlineImporter; +import net.sf.jabref.importer.fileformat.MedlinePlainImporter; +import net.sf.jabref.importer.fileformat.MsBibImporter; +import net.sf.jabref.importer.fileformat.OvidImporter; +import net.sf.jabref.importer.fileformat.PdfContentImporter; +import net.sf.jabref.importer.fileformat.PdfXmpImporter; +import net.sf.jabref.importer.fileformat.RepecNepImporter; +import net.sf.jabref.importer.fileformat.RisImporter; +import net.sf.jabref.importer.fileformat.SilverPlatterImporter; import net.sf.jabref.model.database.BibDatabases; import net.sf.jabref.model.entry.BibEntry; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import net.sf.jabref.*; - public class ImportFormatReader { public static final String BIBTEX_FORMAT = "BibTeX"; /** - * all import formats, in the default order of import formats + * All import formats. + * Sorted accordingly to {@link ImportFormat#compareTo}, which defaults to alphabetically by the name */ private final SortedSet formats = new TreeSet<>(); @@ -86,14 +115,14 @@ public void resetImportFormats() { */ private Optional getByCliId(String cliId) { for (ImportFormat format : formats) { - if (format.getCLIId().equals(cliId)) { + if (format.getId().equals(cliId)) { return Optional.of(format); } } return Optional.empty(); } - public List importFromFile(String format, String filename, OutputPrinter status) + public ParserResult importFromFile(String format, Path file) throws IOException { Optional importer = getByCliId(format); @@ -101,28 +130,18 @@ public List importFromFile(String format, String filename, OutputPrint throw new IllegalArgumentException("Unknown import format: " + format); } - return importFromFile(importer.get(), filename, status); + return importFromFile(importer.get(), file); } - public List importFromFile(ImportFormat importer, String filename, OutputPrinter status) throws IOException { + public ParserResult importFromFile(ImportFormat importer, Path file) throws IOException { Objects.requireNonNull(importer); - Objects.requireNonNull(filename); - File file = new File(filename); - - try (InputStream stream = new FileInputStream(file); - BufferedInputStream bis = new BufferedInputStream(stream)) { + Objects.requireNonNull(file); - bis.mark(Integer.MAX_VALUE); - - if (!importer.isRecognizedFormat(bis)) { - throw new IOException("Wrong file format"); - } + if(!importer.isRecognizedFormat(file)) { + throw new IOException("Wrong file format"); } - try (InputStream stream = new FileInputStream(file); - BufferedInputStream bis = new BufferedInputStream(stream)) { - return importer.importEntries(bis, status); - } + return importer.importDatabase(file); } /** @@ -158,7 +177,7 @@ public String getImportFormatList() { } sb.append(" : "); - sb.append(imFo.getCLIId()); + sb.append(imFo.getId()); sb.append('\n'); } @@ -199,6 +218,9 @@ public UnknownFormatImport(String format, ParserResult parserResult) { } } + public UnknownFormatImport importUnknownFormat(String filename) { + return importUnknownFormat(Paths.get(filename)); + } /** * Tries to import a file by iterating through the available import filters, @@ -208,26 +230,21 @@ public UnknownFormatImport(String format, ParserResult parserResult) { * * @throws IOException */ - public UnknownFormatImport importUnknownFormat(String filename) { - Objects.requireNonNull(filename); + public UnknownFormatImport importUnknownFormat(Path file) { + Objects.requireNonNull(file); // First, see if it is a BibTeX file: try { - ParserResult pr = OpenDatabaseAction.loadDatabase(new File(filename), + ParserResult pr = OpenDatabaseAction.loadDatabase(file.toFile(), Globals.prefs.getDefaultEncoding()); if (pr.getDatabase().hasEntries() || !pr.getDatabase().hasNoStrings()) { - pr.setFile(new File(filename)); + pr.setFile(file.toFile()); return new UnknownFormatImport(ImportFormatReader.BIBTEX_FORMAT, pr); } } catch (IOException ignore) { // Ignored } - // we don't use a provided OutputPrinter (such as the JabRef frame), - // as we don't want to see any outputs from failed importers: - // we expect failures and do not want to report them to the user - OutputPrinterToNull nullOutput = new OutputPrinterToNull(); - // stores ref to best result, gets updated at the next loop List bestResult = null; int bestResultCount = 0; @@ -235,14 +252,16 @@ public UnknownFormatImport importUnknownFormat(String filename) { // Cycle through all importers: for (ImportFormat imFo : getImportFormats()) { - try { + if(!imFo.isRecognizedFormat(file)) { + continue; + } - List entries = importFromFile(imFo, filename, nullOutput); + ParserResult parserResult = importFromFile(imFo, file); + List entries = parserResult.getDatabase().getEntries(); - int entryCount; BibDatabases.purgeEmptyEntries(entries); - entryCount = entries.size(); + int entryCount = entries.size(); if (entryCount > bestResultCount) { bestResult = entries; diff --git a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java index cfe6a97fcfc7..090ff070ea91 100644 --- a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java +++ b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java @@ -19,16 +19,26 @@ import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import javax.swing.JMenuItem; import javax.swing.JOptionPane; -import net.sf.jabref.*; -import net.sf.jabref.gui.*; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.MetaData; +import net.sf.jabref.gui.BasePanel; +import net.sf.jabref.gui.EntryMarker; +import net.sf.jabref.gui.FileDialogs; +import net.sf.jabref.gui.ImportInspectionDialog; +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.ParserResultWarningDialog; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.worker.AbstractWorker; import net.sf.jabref.importer.fileformat.ImportFormat; @@ -98,7 +108,7 @@ public void init() { importError = null; filenames = FileDialogs.getMultipleFiles(frame, new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), - importer == null ? null : importer.getExtensions(), true); + importer == null ? Collections.emptyList() : importer.getExtensions(), true); if (!filenames.isEmpty()) { frame.block(); @@ -118,6 +128,7 @@ public void run() { // We import all files and collect their results: List imports = new ArrayList<>(); for (String filename : filenames) { + Path file = Paths.get(filename); try { if (importer == null) { // Unknown format: @@ -127,9 +138,10 @@ public void run() { } else { frame.output(Localization.lang("Importing in %0 format", importer.getFormatName()) + "..."); // Specific importer: - ParserResult pr = new ParserResult( - Globals.IMPORT_FORMAT_READER.importFromFile(importer, - filename, frame)); + ParserResult pr = Globals.IMPORT_FORMAT_READER.importFromFile(importer, file); + if (pr.hasWarnings()) { + frame.showMessage(pr.getErrorMessage()); + } imports.add(new ImportFormatReader.UnknownFormatImport(importer .getFormatName(), pr)); diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index db4975320340..0921e247b55b 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -89,7 +89,8 @@ public void actionPerformed(ActionEvent e) { if (showDialog) { List chosenStrings = FileDialogs.getMultipleFiles(frame, - new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), ".bib", true); + new File(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)), Collections.singletonList(".bib"), + true); for (String chosen : chosenStrings) { if (chosen != null) { filesToOpen.add(new File(chosen)); diff --git a/src/main/java/net/sf/jabref/importer/ParserResult.java b/src/main/java/net/sf/jabref/importer/ParserResult.java index 85c791c4383d..8e961d04c811 100644 --- a/src/main/java/net/sf/jabref/importer/ParserResult.java +++ b/src/main/java/net/sf/jabref/importer/ParserResult.java @@ -17,14 +17,15 @@ import java.io.File; import java.nio.charset.Charset; - -import java.util.List; -import java.util.Map; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.List; +import java.util.Map; -import net.sf.jabref.*; +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.MetaData; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabases; import net.sf.jabref.model.entry.BibEntry; @@ -49,6 +50,9 @@ public class ParserResult { private boolean invalid; private boolean toOpenTab; + public ParserResult() { + this(Collections.emptyList()); + } public ParserResult(Collection entries) { this(BibDatabases.createDatabase(BibDatabases.purgeEmptyEntries(entries)), null, new HashMap<>()); @@ -60,6 +64,12 @@ public ParserResult(BibDatabase base, MetaData metaData, Map this.entryTypes = entryTypes; } + public static ParserResult fromErrorMessage(String message) { + ParserResult parserResult = new ParserResult(); + parserResult.addWarning(message); + return parserResult; + } + /** * Check if this base is marked to be added to the currently open tab. Default is false. * diff --git a/src/main/java/net/sf/jabref/importer/ZipFileChooser.java b/src/main/java/net/sf/jabref/importer/ZipFileChooser.java index fce892fff4fa..728f736052af 100644 --- a/src/main/java/net/sf/jabref/importer/ZipFileChooser.java +++ b/src/main/java/net/sf/jabref/importer/ZipFileChooser.java @@ -110,7 +110,7 @@ public ZipFileChooser(ImportCustomizationDialog importCustomizationDialog, ZipFi try { ImportFormat importFormat = importer.getInstance(); importer.setName(importFormat.getFormatName()); - importer.setCliId(importFormat.getCLIId()); + importer.setCliId(importFormat.getId()); importCustomizationDialog.addOrReplaceImporter(importer); dispose(); } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException exc) { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index 15bf27e25f35..c0d096115521 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -22,24 +22,26 @@ import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.Objects; import java.util.Optional; -import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import net.sf.jabref.importer.*; -import net.sf.jabref.importer.fileformat.BibtexParser; -import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.importer.ImportInspector; +import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; +import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.logic.util.DOI; +import net.sf.jabref.model.entry.BibEntry; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; public class DOItoBibTeXFetcher implements EntryFetcher { @@ -56,7 +58,11 @@ public void stopFetching() { @Override public boolean processQuery(String query, ImportInspector inspector, OutputPrinter status) { - BibEntry entry = getEntryFromDOI(query, status); + ParserResult parserResult = new ParserResult(); + BibEntry entry = getEntryFromDOI(query, parserResult); + if(parserResult.hasWarnings()) { + status.showMessage(parserResult.getErrorMessage()); + } if (entry != null) { inspector.addEntry(entry); return true; @@ -80,15 +86,14 @@ public JPanel getOptionsPanel() { return null; } - public BibEntry getEntryFromDOI(String doiStr, OutputPrinter status) { + public BibEntry getEntryFromDOI(String doiStr, ParserResult parserResult) { + Objects.requireNonNull(parserResult); + DOI doi; try { doi = new DOI(doiStr); } catch (IllegalArgumentException e) { - status.showMessage(Localization.lang("Invalid DOI: '%0'.", doiStr), - Localization.lang("Get BibTeX entry from DOI"), - JOptionPane.INFORMATION_MESSAGE); - LOGGER.warn("Invalid DOI", e); + parserResult.addWarning(Localization.lang("Invalid DOI: '%0'.", doiStr)); return null; } @@ -114,11 +119,7 @@ public BibEntry getEntryFromDOI(String doiStr, OutputPrinter status) { dl.addParameters("Accept", "application/x-bibtex"); bibtexString = dl.downloadToString(StandardCharsets.UTF_8); } catch (FileNotFoundException e) { - if (status != null) { - status.showMessage(Localization.lang("Unknown DOI: '%0'.", doi.getDOI()), - Localization.lang("Get BibTeX entry from DOI"), - JOptionPane.INFORMATION_MESSAGE); - } + parserResult.addWarning(Localization.lang("Unknown DOI: '%0'.", doi.getDOI())); LOGGER.debug("Unknown DOI", e); return null; } catch (IOException e) { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java index acb015faf357..24d620362123 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java @@ -20,6 +20,8 @@ import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -150,7 +152,7 @@ public boolean processQuery(String query, ImportInspector iIDialog, OutputPrinte if (cleanQuery.matches("\\d+[,\\d+]*")) { frameOP.setStatus(Localization.lang("Fetching Medline by id...")); - List bibs = MedlineImporter.fetchMedline(cleanQuery, frameOP); + List bibs = fetchMedline(cleanQuery, frameOP); if (bibs.isEmpty()) { frameOP.showMessage(Localization.lang("No references found")); @@ -208,7 +210,7 @@ public boolean processQuery(String query, ImportInspector iIDialog, OutputPrinte // get the ids from entrez result = getIds(searchTerm, i, noToFetch); - List bibs = MedlineImporter.fetchMedline(result.ids, frameOP); + List bibs = fetchMedline(result.ids, frameOP); for (BibEntry entry : bibs) { iIDialog.addEntry(entry); } @@ -222,6 +224,24 @@ public boolean processQuery(String query, ImportInspector iIDialog, OutputPrinte return false; } + /** + * Fetch and parse an medline item from eutils.ncbi.nlm.nih.gov. + * + * @param id One or several ids, separated by "," + * + * @return Will return an empty list on error. + */ + private static List fetchMedline(String id, OutputPrinter status) { + String baseUrl = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&rettype=citation&id=" + + id; + try { + URL url = new URL(baseUrl); + URLConnection data = url.openConnection(); + return new MedlineImporter().importEntries(data.getInputStream(), status); + } catch (IOException e) { + return new ArrayList<>(); + } + } static class SearchResult { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java index 2f9dc9a6389a..5d768b61def0 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java @@ -21,7 +21,7 @@ import java.util.*; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; /** @@ -32,37 +32,29 @@ */ public class BiblioscapeImporter extends ImportFormat { - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "Biblioscape"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "biblioscape"; + public List getExtensions() { + return null; } - /** - * Check whether the source is in the correct format for this importer. - */ @Override - public boolean isRecognizedFormat(InputStream in) throws IOException { + public String getDescription() { + return null; + } + + @Override + public boolean isRecognizedFormat(InputStream in) { + Objects.requireNonNull(in); return true; } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { List bibItems = new ArrayList<>(); BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream)); @@ -291,12 +283,12 @@ public List importEntries(InputStream stream, OutputPrinter status) th } // continuation (folding) of previous line if (previousLine == null) { - return Collections.emptyList(); + return new ParserResult(); } previousLine.append(line.trim()); } - return bibItems; + return new ParserResult(bibItems); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java index 665b96c53f2b..a7969758f83c 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java @@ -20,13 +20,13 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.regex.Pattern; - import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -43,28 +43,21 @@ public class BibteXMLImporter extends ImportFormat { private static final Pattern START_PATTERN = Pattern.compile(" getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; } - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -80,12 +73,9 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { } } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { + Objects.requireNonNull(stream); List bibItems = new ArrayList<>(); @@ -107,16 +97,15 @@ public List importEntries(InputStream stream, OutputPrinter status) th } catch (javax.xml.parsers.ParserConfigurationException e) { LOGGER.error("Error with XML parser configuration", e); - status.showMessage(e.getLocalizedMessage()); + return ParserResult.fromErrorMessage(e.getLocalizedMessage()); } catch (org.xml.sax.SAXException e) { LOGGER.error("Error during XML parsing", e); - status.showMessage(e.getLocalizedMessage()); + return ParserResult.fromErrorMessage(e.getLocalizedMessage()); } catch (IOException e) { LOGGER.error("Error during file import", e); - status.showMessage(e.getLocalizedMessage()); + return ParserResult.fromErrorMessage(e.getLocalizedMessage()); } - return bibItems; - + return new ParserResult(bibItems); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java index 5eaf75eee5e5..a0822c906bc6 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java @@ -17,13 +17,12 @@ import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; -import net.sf.jabref.model.entry.BibEntry; /** * This importer exists only to enable `--importToOpen someEntry.bib` @@ -38,24 +37,14 @@ public class BibtexImporter extends ImportFormat { * https://github.com/JabRef/jabref/pull/379#issuecomment-158685726 for more details. */ @Override - public boolean isRecognizedFormat(InputStream in) throws IOException { + public boolean isRecognizedFormat(InputStream in) { + Objects.requireNonNull(in); return true; } - /** - * Parses the given input stream. - * Only plain bibtex entries are returned. - * That especially means that metadata is ignored. - * - * @param in the inputStream to read from - * @param status the OutputPrinter to put status to - * @return a list of BibTeX entries contained in the given inputStream - */ @Override - public List importEntries(InputStream in, OutputPrinter status) - throws IOException { - ParserResult pr = BibtexParser.parse(ImportFormatReader.getReaderDefaultEncoding(in)); - return new ArrayList<>(pr.getDatabase().getEntries()); + public ParserResult importDatabase(InputStream in) throws IOException { + return BibtexParser.parse(ImportFormatReader.getReaderDefaultEncoding(in)); } @Override @@ -64,8 +53,13 @@ public String getFormatName() { } @Override - public String getExtensions() { - return "bib"; + public List getExtensions() { + return Collections.singletonList("bib"); + } + + @Override + public String getDescription() { + return null; } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java index ab43d01fdc06..4d0d5d78addb 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java @@ -20,10 +20,11 @@ import java.io.InputStream; import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; /** @@ -37,30 +38,26 @@ public class CopacImporter extends ImportFormat { private static final Pattern COPAC_PATTERN = Pattern.compile("^\\s*TI- "); - - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "Copac"; } - /* - * (non-Javadoc) - * - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "cpc"; + public List getExtensions() { + return null; } + @Override + public String getId() { + return "cpc"; + } + @Override + public String getDescription() { + return null; + } - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -77,15 +74,9 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { - if (stream == null) { - throw new IOException("No stream given."); - } + public ParserResult importDatabase(InputStream stream) throws IOException { + Objects.requireNonNull(stream); List entries = new LinkedList<>(); StringBuilder sb = new StringBuilder(); @@ -166,7 +157,7 @@ public List importEntries(InputStream stream, OutputPrinter status) th results.add(b); } - return results; + return new ParserResult(results); } private static void setOrAppend(BibEntry b, String field, String value, String separator) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java index 2d100f08dac4..a4445eff3190 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java @@ -24,7 +24,7 @@ import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -44,27 +44,26 @@ public class EndnoteImporter extends ImportFormat { private static final Pattern A_PATTERN = Pattern.compile("%A .*"); private static final Pattern E_PATTERN = Pattern.compile("%E .*"); - - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "Refer/Endnote"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { + public List getExtensions() { + return null; + } + + @Override + public String getId() { return "refer"; } - /** - * Check whether the source is in the correct format for this importer. - */ + @Override + public String getDescription() { + return null; + } + @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -80,12 +79,8 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { @@ -280,7 +275,7 @@ else if ("P".equals(prefix)) { } - return bibitems; + return new ParserResult(bibitems); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index 421007b5d6a8..ceadc4dd59b5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -25,8 +25,8 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Scanner; import javax.xml.stream.XMLInputFactory; @@ -34,18 +34,18 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.Globals; import net.sf.jabref.JabRef; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.EntryType; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + /** * This importer parses text format citations using the online API of FreeCite - * Open Source Citation Parser http://freecite.library.brown.edu/ @@ -56,21 +56,21 @@ public class FreeCiteImporter extends ImportFormat { @Override public boolean isRecognizedFormat(InputStream in) throws IOException { - // TODO: We don't know how to recognize text files, therefore we return - // "false" + Objects.requireNonNull(in); + // TODO: We don't know how to recognize text files, therefore we return "false" return false; } @Override - public List importEntries(InputStream in, OutputPrinter status) + public ParserResult importDatabase(InputStream in) throws IOException { try (Scanner scan = new Scanner(in)) { String text = scan.useDelimiter("\\A").next(); - return importEntries(text, status); + return importEntries(text); } } - public List importEntries(String text, OutputPrinter status) { + public ParserResult importEntries(String text) { // URLencode the string for transmission String urlencodedCitation = null; try { @@ -87,10 +87,10 @@ public List importEntries(String text, OutputPrinter status) { conn = url.openConnection(); } catch (MalformedURLException e) { LOGGER.warn("Bad URL", e); - return Collections.emptyList(); + return new ParserResult(); } catch (IOException e) { LOGGER.warn("Could not download", e); - return Collections.emptyList(); + return new ParserResult(); } try { conn.setRequestProperty("accept", "text/xml"); @@ -104,13 +104,11 @@ public List importEntries(String text, OutputPrinter status) { } catch (IllegalStateException e) { LOGGER.warn("Already connected.", e); } catch (IOException e) { - status.showMessage(Localization.lang("Unable to connect to FreeCite online service.")); LOGGER.warn("Unable to connect to FreeCite online service.", e); - return Collections.emptyList(); + return ParserResult.fromErrorMessage(Localization.lang("Unable to connect to FreeCite online service.")); } // output is in conn.getInputStream(); // new InputStreamReader(conn.getInputStream()) - List res = new ArrayList<>(); XMLInputFactory factory = XMLInputFactory.newInstance(); @@ -214,8 +212,8 @@ public List importEntries(String text, OutputPrinter status) { e.setType(type); // autogenerate label (BibTeX key) - LabelPatternUtil.makeLabel(JabRef.mainFrame.getCurrentBasePanel().getBibDatabaseContext().getMetaData(), JabRef.mainFrame.getCurrentBasePanel().getDatabase(), e); - + LabelPatternUtil.makeLabel(JabRef.mainFrame.getCurrentBasePanel().getBibDatabaseContext().getMetaData(), + JabRef.mainFrame.getCurrentBasePanel().getDatabase(), e); res.add(e); } parser.next(); @@ -223,10 +221,10 @@ public List importEntries(String text, OutputPrinter status) { parser.close(); } catch (IOException | XMLStreamException ex) { LOGGER.warn("Could not parse", ex); - return Collections.emptyList(); + return new ParserResult(); } - return res; + return new ParserResult(res); } @Override @@ -234,4 +232,14 @@ public String getFormatName() { return "text citations"; } + @Override + public List getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; + } + } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java index bc1baa6229a0..fcc1cda2a3b1 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java @@ -15,68 +15,85 @@ */ package net.sf.jabref.importer.fileformat; +import java.io.BufferedInputStream; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.util.List; +import java.util.Objects; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; /** * Role of an importer for JabRef. - * - *

Importers are sorted according to following criteria - *

  1. - * custom importers come first, then importers shipped with JabRef - *
  2. - * then importers are sorted by name. - *
- *

*/ public abstract class ImportFormat implements Comparable { /** * Using this when I have no database open or when I read * non bibtex file formats (used by the ImportFormatReader.java) + * + * TODO: Is this field really needed or would calling IdGenerator.next() suffice? */ public static final String DEFAULT_BIBTEXENTRY_ID = "__ID"; - private boolean isCustomImporter; - - - /** - * Constructor for custom importers. - */ - public ImportFormat() { - this.isCustomImporter = false; - } - /** * Check whether the source is in the correct format for this importer. + * + * The effect of this method is primarily to avoid unnecessary processing of + * files when searching for a suitable import format. If this method returns + * false, the import routine will move on to the next import format. + * + * Thus the correct behaviour is to return false if it is certain that the file is + * not of the suitable type, and true otherwise. Returning true is the safe choice if not certain. */ public abstract boolean isRecognizedFormat(InputStream in) throws IOException; + public boolean isRecognizedFormat(Path filePath) throws IOException { + try (InputStream stream = new FileInputStream(filePath.toFile()); + BufferedInputStream bufferedStream = new BufferedInputStream(stream)) { + + bufferedStream.mark(Integer.MAX_VALUE); + + return isRecognizedFormat(bufferedStream); + } + } + /** - * Parse the entries in the source, and return a List of BibEntry - * objects. + * Parse the database in the source. * * This method can be called in two different contexts - either when importing in * a specified format, or when importing in unknown format. In the latter case, * JabRef cycles through all available import formats. No error messages or feedback * is displayed from individual import formats in this case. * - * If importing in a specified format, and an empty list is returned, JabRef reports - * that no entries were found. If an IOException is thrown, JabRef displays the exception's - * message in unmodified form. + * If importing in a specified format and an empty database is returned, JabRef reports + * that no entries were found. * - * This method should never return null. Return an empty list instead. + * This method should never return null. * - * TODO the return type should be changed to "ParseResult" as the parser could use a different encoding than the default encoding + * @param in the input stream to read from */ - public abstract List importEntries(InputStream in, OutputPrinter status) throws IOException; + public abstract ParserResult importDatabase(InputStream in) throws IOException ; + + public ParserResult importDatabase(Path filePath) throws IOException { + try (InputStream stream = new FileInputStream(filePath.toFile()); + BufferedInputStream bufferedStream = new BufferedInputStream(stream)) { + + return importDatabase(bufferedStream); + } + } + + @Deprecated + public List importEntries(InputStream in, OutputPrinter printer) throws IOException { + return importDatabase(in).getDatabase().getEntries(); + } /** - * Name of this import format. + * Returns the name of this import format. * *

The name must be unique.

* @@ -85,20 +102,20 @@ public ImportFormat() { public abstract String getFormatName(); /** - * Extensions that this importer can read. + * Returns the file extensions that this importer can read. + * The extension should contain the leading dot, so for example ".bib" * - * @return comma separated list of extensions or null for the default + * @return list of supported file extensions (not null but may be empty) */ - public String getExtensions() { - return null; - } + public abstract List getExtensions(); /** - * Short, one token ID to identify the format from the command line. + * Returns a one-word ID which identifies this import format. + * Used for example, to identify the format when used from the command line. * - * @return command line ID + * @return ID, must be unique and not null */ - public String getCLIId() { + public String getId() { String id = getFormatName(); StringBuilder result = new StringBuilder(id.length()); for (int i = 0; i < id.length(); i++) { @@ -111,9 +128,9 @@ public String getCLIId() { } /** - * Description of the ImportFormat. + * Returns the description of the import format. * - *

Implementors of ImportFormats should override this. Ideally, it should specify + * The description should specify *

  • * what kind of entries from what sources and based on what specification it is able to import *
  • @@ -122,80 +139,32 @@ public String getCLIId() { * * @return description of the import format */ - public String getDescription() { - return "No description available for " + getFormatName() + "."; - } - - /** - * Sets if this is a custom importer. - * - *

    For custom importers added dynamically to JabRef, this will be - * set automatically by JabRef.

    - * - * @param isCustomImporter if this is a custom importer - */ - public final void setIsCustomImporter(boolean isCustomImporter) { - this.isCustomImporter = isCustomImporter; - } - - /** - * Wether this importer is a custom importer. - * - *

    Custom importers will have precedence over built-in importers.

    - * - * @return wether this is a custom importer - */ - public final boolean isCustomImporter() { - return this.isCustomImporter; - } + public abstract String getDescription(); - /* - * (non-Javadoc) - * @see java.lang.Object#hashCode() - */ @Override public int hashCode() { return getFormatName().hashCode(); } - /* - * (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public boolean equals(Object obj) { + if(obj == null) { + return false; } - - if (o instanceof ImportFormat) { - ImportFormat format = (ImportFormat) o; - return (format.isCustomImporter() == isCustomImporter()) && format.getFormatName().equals(getFormatName()); + if(!(obj instanceof ImportFormat)) { + return false; } - return false; + ImportFormat other = (ImportFormat)obj; + return Objects.equals(this.getFormatName(), other.getFormatName()); } - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ @Override public String toString() { return getFormatName(); } - /* - * (non-Javadoc) - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ @Override - public int compareTo(ImportFormat importer) { - int result; - if (isCustomImporter() == importer.isCustomImporter()) { - result = getFormatName().compareTo(importer.getFormatName()); - } else { - result = isCustomImporter() ? 1 : -1; - } - return result; + public int compareTo(ImportFormat o) { + return getFormatName().compareTo(o.getFormatName()); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java index 1e4a883843e2..efffc671eb80 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java @@ -15,20 +15,19 @@ */ package net.sf.jabref.importer.fileformat; -import java.io.InputStream; import java.io.BufferedReader; import java.io.IOException; -import java.util.List; -import java.util.Map; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; - -import java.util.regex.Pattern; +import net.sf.jabref.model.entry.BibEntry; /** * INSPEC format importer. @@ -37,27 +36,21 @@ public class InspecImporter extends ImportFormat { private static final Pattern INSPEC_PATTERN = Pattern.compile("Record.*INSPEC.*"); - - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "INSPEC"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "inspec"; + public List getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; } - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { // Our strategy is to look for the "PY " line. @@ -73,15 +66,12 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Parse the entries in the source, and return a List of BibEntry objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); - String str; try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { + String str; while ((str = in.readLine()) != null) { if (str.length() < 2) { continue; @@ -157,6 +147,6 @@ public List importEntries(InputStream stream, OutputPrinter status) th } - return bibitems; + return new ParserResult(bibitems); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java index b827ea1d5506..eae142a0cf4e 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java @@ -22,14 +22,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.formatter.CaseChangers; -import net.sf.jabref.model.entry.MonthUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.MonthUtil; /** * Importer for the ISI Web of Science, INSPEC and Medline format. @@ -57,29 +58,26 @@ public class IsiImporter extends ImportFormat { private static final Pattern ISI_PATTERN = Pattern.compile("FN ISI Export Format|VR 1.|PY \\d{4}"); - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "ISI"; } - /* - * (non-Javadoc) - * - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "isi"; + public List getExtensions() { + return null; } + @Override + public String getId() { + return "isi"; + } + @Override + public String getDescription() { + return null; + } - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -106,8 +104,6 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - - public static void processSubSup(Map map) { String[] subsup = {"title", "abstract", "review", "notes"}; @@ -156,15 +152,9 @@ private static void processCapitalization(Map map) { } } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { - if (stream == null) { - throw new IOException("No stream given."); - } + public ParserResult importDatabase(InputStream stream) throws IOException { + Objects.requireNonNull(stream); List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); @@ -355,7 +345,7 @@ public List importEntries(InputStream stream, OutputPrinter status) th bibitems.add(b); } - return bibitems; + return new ParserResult(bibitems); } private static String parsePages(String value) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java index 72c9068acb17..1d849ffce803 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java @@ -16,16 +16,15 @@ package net.sf.jabref.importer.fileformat; import java.io.*; -import java.net.URL; -import java.net.URLConnection; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -46,19 +45,21 @@ public String getFormatName() { return "Medline"; } - /* - * (non-Javadoc) - * - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { + public List getExtensions() { + return null; + } + + @Override + public String getId() { return "medline"; } - /** - * Check whether the source is in the correct format for this importer. - */ + @Override + public String getDescription() { + return null; + } + @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -77,31 +78,9 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Fetch and parse an medline item from eutils.ncbi.nlm.nih.gov. - * - * @param id One or several ids, separated by "," - * - * @return Will return an empty list on error. - */ - public static List fetchMedline(String id, OutputPrinter status) { - String baseUrl = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&rettype=citation&id=" + - id; - try { - URL url = new URL(baseUrl); - URLConnection data = url.openConnection(); - return new MedlineImporter().importEntries(data.getInputStream(), status); - } catch (IOException e) { - return new ArrayList<>(); - } - } - - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { + Objects.requireNonNull(stream); // Obtain a factory object for creating SAX parsers SAXParserFactory parserFactory = SAXParserFactory.newInstance(); @@ -135,18 +114,18 @@ public List importEntries(InputStream stream, OutputPrinter status) th // When you're done, report the results stored by your handler // object bibItems.addAll(handler.getItems()); - } catch (javax.xml.parsers.ParserConfigurationException e1) { - LOGGER.error("Error with XML parser configuration", e1); - status.showMessage(e1.getLocalizedMessage()); - } catch (org.xml.sax.SAXException e2) { - LOGGER.error("Error during XML parsing", e2); - status.showMessage(e2.getLocalizedMessage()); - } catch (IOException e3) { - LOGGER.error("Error during file import", e3); - status.showMessage(e3.getLocalizedMessage()); + } catch (javax.xml.parsers.ParserConfigurationException e) { + LOGGER.error("Error with XML parser configuration", e); + return ParserResult.fromErrorMessage(e.getLocalizedMessage()); + } catch (org.xml.sax.SAXException e) { + LOGGER.error("Error during XML parsing", e); + return ParserResult.fromErrorMessage(e.getLocalizedMessage()); + } catch (IOException e) { + LOGGER.error("Error during file import", e); + return ParserResult.fromErrorMessage(e.getLocalizedMessage()); } - return bibItems; + return new ParserResult(bibItems); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index ceec580d3cee..5e17ad000754 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -17,19 +17,19 @@ package net.sf.jabref.importer.fileformat; -import java.util.regex.Pattern; -import java.io.InputStream; import java.io.BufferedReader; import java.io.IOException; -import java.util.List; -import java.util.Map; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; +import net.sf.jabref.model.entry.BibEntry; /** * Importer for the MEDLINE Plain format. @@ -45,27 +45,21 @@ public class MedlinePlainImporter extends ImportFormat { private static final Pattern PMC_PATTERN = Pattern.compile("PMC.*-.*"); private static final Pattern PMCR_PATTERN = Pattern.compile("PMCR.*-.*"); - - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "MedlinePlain"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "medlineplain"; + public List getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; } - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -84,12 +78,8 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { @@ -285,7 +275,7 @@ else if ("AID".equals(lab)) { } - return bibitems; + return new ParserResult(bibitems); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java index b17835c34c9b..c92503c7be59 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java @@ -18,12 +18,12 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; +import java.util.Objects; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.msbib.MSBibDatabase; import org.w3c.dom.Document; @@ -38,13 +38,9 @@ public class MsBibImporter extends ImportFormat { @Override public boolean isRecognizedFormat(InputStream in) throws IOException { + Objects.requireNonNull(in); /* - This method is available for checking if a file can be of the MSBib type. - The effect of this method is primarily to avoid unnecessary processing of - files when searching for a suitable import format. If this method returns - false, the import routine will move on to the next import format. - The correct behaviour is to return false if it is certain that the file is not of the MsBib type, and true otherwise. Returning true is the safe choice if not certain. @@ -61,26 +57,27 @@ public boolean isRecognizedFormat(InputStream in) throws IOException { return (docin == null) || docin.getDocumentElement().getTagName().contains("Sources"); } - /** - * String used to identify this import filter on the command line. - * @return "msbib" - */ - public String getCommandLineId() { - return "msbib"; - } - @Override - public List importEntries(InputStream in, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream in) throws IOException { + Objects.requireNonNull(in); MSBibDatabase dbase = new MSBibDatabase(); - - return dbase.importEntries(in); + return new ParserResult(dbase.importEntries(in)); } @Override public String getFormatName() { - // This method should return the name of this import format. return "MSBib"; } + @Override + public List getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; + } + } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java index 2ce39b06723a..c922e3484f9f 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java @@ -15,19 +15,21 @@ */ package net.sf.jabref.importer.fileformat; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.io.InputStream; import java.io.BufferedReader; import java.io.IOException; -import java.util.List; -import java.util.Map; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.*; +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.model.entry.AuthorList; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.IdGenerator; /** * Imports an Ovid file. @@ -53,28 +55,22 @@ public class OvidImporter extends ImportFormat { private static final Pattern OVID_PATTERN = Pattern.compile(OVID_PATTERN_STRING); private static final int MAX_ITEMS = 50; - /** - * Return the name of this import format. - */ + @Override public String getFormatName() { return "Ovid"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "ovid"; + public List getExtensions() { + return null; } + @Override + public String getDescription() { + return null; + } - - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -93,12 +89,8 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { @@ -242,7 +234,7 @@ public List importEntries(InputStream stream, OutputPrinter status) th } - return bibitems; + return new ParserResult(bibitems); } /** diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index 3d38236ce475..b93460ff0e19 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -1,8 +1,18 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.importer.ImportInspector; -import net.sf.jabref.importer.OutputPrinter; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fetcher.DOItoBibTeXFetcher; +import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.logic.xmp.EncryptedPdfsNotSupportedException; import net.sf.jabref.logic.xmp.XMPUtil; @@ -10,23 +20,10 @@ import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.EntryType; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import com.google.common.base.Strings; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.util.PDFTextStripper; -import com.google.common.base.Strings; - -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * PdfContentImporter parses data of the first page of the PDF and creates a BibTeX entry. *

    @@ -35,7 +32,6 @@ * Integrating XMP support is future work */ public class PdfContentImporter extends ImportFormat { - private static final Log LOGGER = LogFactory.getLog(PdfContentImporter.class); private static final Pattern YEAR_EXTRACT_PATTERN = Pattern.compile("\\d{4}"); // we can store the DOItoBibTeXFetcher as single reference as the fetcher doesn't hold internal state @@ -180,41 +176,24 @@ private static String streamlineTitle(String title) { @Override public boolean isRecognizedFormat(InputStream in) throws IOException { + Objects.requireNonNull(in); return false; } @Override - public List importEntries(InputStream in, OutputPrinter status) throws IOException { - final ArrayList result = new ArrayList<>(1); + public ParserResult importDatabase(InputStream in) throws IOException { + Objects.requireNonNull(in); + final ArrayList result = new ArrayList<>(1); try (PDDocument document = XMPUtil.loadWithAutomaticDecryption(in)) { String firstPageContents = getFirstPageContents(document); Optional doi = DOI.findInText(firstPageContents); if (doi.isPresent()) { - ImportInspector inspector = new ImportInspector() { - - @Override - public void toFront() { - // Do nothing - } - - @Override - public void setProgress(int current, int max) { - // Do nothing - } - - @Override - public void addEntry(BibEntry entry) { - // add the entry to the result object - result.add(entry); - } - }; - - DOI_TO_BIBTEX_FETCHER.processQuery(doi.get().getDOI(), inspector, status); - if (!result.isEmpty()) { - return result; - } + ParserResult parserResult = new ParserResult(result); + BibEntry entry = DOI_TO_BIBTEX_FETCHER.getEntryFromDOI(doi.get().getDOI(), parserResult); + parserResult.getDatabase().insertEntry(entry); + return parserResult; } // idea: split[] contains the different lines @@ -231,7 +210,7 @@ public void addEntry(BibEntry entry) { if (i >= lines.length) { // PDF could not be parsed or is empty // return empty list - return result; + return new ParserResult(); } // we start at the current line @@ -480,10 +459,12 @@ public void addEntry(BibEntry entry) { result.add(entry); } catch (EncryptedPdfsNotSupportedException e) { - LOGGER.info("Decryption not supported"); - return Collections.EMPTY_LIST; + return ParserResult.fromErrorMessage(Localization.lang("Decryption not supported.")); + } catch(IOException exception) { + return ParserResult.fromErrorMessage(exception.getLocalizedMessage()); } - return result; + + return new ParserResult(result); } private String getFirstPageContents(PDDocument document) throws IOException { @@ -589,4 +570,14 @@ public String getFormatName() { return "PDFcontent"; } + @Override + public List getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; + } + } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java index 65d54976c4fe..1dc8fd50aab2 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java @@ -18,9 +18,9 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; +import java.util.Objects; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.xmp.XMPUtil; @@ -34,12 +34,19 @@ public String getFormatName() { return Localization.lang("XMP-annotated PDF"); } - /** - * Returns a list of all BibtexEntries found in the inputstream. - */ @Override - public List importEntries(InputStream in, OutputPrinter status) throws IOException { - return XMPUtil.readXMP(in); + public List getExtensions() { + return null; + } + + @Override + public ParserResult importDatabase(InputStream in) throws IOException { + Objects.requireNonNull(in); + try { + return new ParserResult(XMPUtil.readXMP(in)); + } catch (IOException exception) { + return ParserResult.fromErrorMessage(exception.getLocalizedMessage()); + } } /** @@ -48,16 +55,18 @@ public List importEntries(InputStream in, OutputPrinter status) throws */ @Override public boolean isRecognizedFormat(InputStream in) throws IOException { + Objects.requireNonNull(in); return XMPUtil.hasMetadata(in); } - /** - * String used to identify this import filter on the command line. - * - * @return "xmp" - */ - public String getCommandLineId() { + @Override + public String getId() { return "xmp"; } + @Override + public String getDescription() { + return null; + } + } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index a8cb862a2172..c7cd78f99f23 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -25,9 +25,9 @@ import java.util.*; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.IdGenerator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -162,37 +162,21 @@ public class RepecNepImporter extends ImportFormat { private String preLine = ""; private boolean inOverviewSection; - - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "REPEC New Economic Papers (NEP)"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { + public String getId() { return "repecnep"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getExtensions() - */ @Override - public String getExtensions() { - return ".txt"; + public List getExtensions() { + return Collections.singletonList(".txt"); } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getDescription() - */ @Override public String getDescription() { return @@ -203,10 +187,6 @@ public String getDescription() { + "contains the line \"nep.repec.org\"."; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#isRecognizedFormat(java.io.InputStream) - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { // read the first couple of lines @@ -427,12 +407,10 @@ private boolean isStartOfWorkingPaper() { return this.lastLine.matches("\\d+\\.\\s.*") && !this.inOverviewSection && "".equals(this.preLine.trim()); } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#importEntries(java.io.InputStream) - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { + Objects.requireNonNull(stream); + List bibitems = new ArrayList<>(); String paperNoStr = null; this.line = 0; @@ -475,14 +453,11 @@ public List importEntries(InputStream stream, OutputPrinter status) th if (paperNoStr != null) { message += ", paper no. " + paperNoStr + ": "; } - message += e.getMessage(); + message += e.getLocalizedMessage(); LOGGER.error(message, e); - if (!(e instanceof IOException)) { - e = new IOException(message); - } - throw (IOException) e; + return ParserResult.fromErrorMessage(message); } - return bibitems; + return new ParserResult(bibitems); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java index 063c0b602a12..41c03516efeb 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java @@ -15,18 +15,20 @@ */ package net.sf.jabref.importer.fileformat; -import java.util.regex.Pattern; -import java.io.InputStream; import java.io.BufferedReader; import java.io.IOException; -import java.util.List; -import java.util.Map; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.*; +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.model.entry.AuthorList; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.MonthUtil; /** * Imports a Biblioscape Tag File. The format is described on @@ -38,26 +40,21 @@ public class RisImporter extends ImportFormat { private static final Pattern RECOGNIZED_FORMAT_PATTERN = Pattern.compile("TY - .*"); - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "RIS"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "ris"; + public List getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; } - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { @@ -74,12 +71,8 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { @@ -284,7 +277,7 @@ else if ("ID".equals(lab)) { } - return bibitems; + return new ParserResult(bibitems); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java index ff676bc73e4b..1cf5cca5f072 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java @@ -15,19 +15,18 @@ */ package net.sf.jabref.importer.fileformat; -import java.io.InputStream; import java.io.BufferedReader; import java.io.IOException; -import java.util.List; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.regex.Pattern; import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; - -import java.util.regex.Pattern; +import net.sf.jabref.model.entry.BibEntry; /** * Imports a SilverPlatter exported file. This is a poor format to parse, @@ -37,27 +36,21 @@ public class SilverPlatterImporter extends ImportFormat { private static final Pattern START_PATTERN = Pattern.compile("Record.*INSPEC.*"); - - /** - * Return the name of this import format. - */ @Override public String getFormatName() { return "SilverPlatter"; } - /* - * (non-Javadoc) - * @see net.sf.jabref.imports.ImportFormat#getCLIId() - */ @Override - public String getCLIId() { - return "silverplatter"; + public List getExtensions() { + return null; + } + + @Override + public String getDescription() { + return null; } - /** - * Check whether the source is in the correct format for this importer. - */ @Override public boolean isRecognizedFormat(InputStream stream) throws IOException { try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { @@ -81,12 +74,8 @@ public boolean isRecognizedFormat(InputStream stream) throws IOException { return false; } - /** - * Parse the entries in the source, and return a List of BibEntry - * objects. - */ @Override - public List importEntries(InputStream stream, OutputPrinter status) throws IOException { + public ParserResult importDatabase(InputStream stream) throws IOException { List bibitems = new ArrayList<>(); try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { boolean isChapter = false; @@ -216,6 +205,6 @@ public List importEntries(InputStream stream, OutputPrinter status) th } } - return bibitems; + return new ParserResult(bibitems); } } diff --git a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTest.java b/src/test/java/net/sf/jabref/importer/ImportFormatReaderIntegrationTest.java similarity index 76% rename from src/test/java/net/sf/jabref/importer/ImportFormatReaderTest.java rename to src/test/java/net/sf/jabref/importer/ImportFormatReaderIntegrationTest.java index 7b7090602497..8d1ad266ed47 100644 --- a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTest.java +++ b/src/test/java/net/sf/jabref/importer/ImportFormatReaderIntegrationTest.java @@ -1,36 +1,34 @@ package net.sf.jabref.importer; -import static org.junit.Assert.*; - import java.io.IOException; import java.net.URISyntaxException; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import static org.junit.Assert.assertEquals; @RunWith(Parameterized.class) -public class ImportFormatReaderTest { +public class ImportFormatReaderIntegrationTest { private ImportFormatReader reader; - private final String resourceName; private final int count; public final String format; - private final String fileName; + private final Path file; - public ImportFormatReaderTest(String resource, String format, int count) throws URISyntaxException { - this.resourceName = resource; + public ImportFormatReaderIntegrationTest(String resource, String format, int count) throws URISyntaxException { this.format = format; this.count = count; - this.fileName = Paths.get(ImportFormatReaderTest.class.getResource(resourceName).toURI()).toString(); + this.file = Paths.get(ImportFormatReaderIntegrationTest.class.getResource(resource).toURI()); } @@ -43,14 +41,13 @@ public void setUp() { @Test public void testImportUnknownFormat() { - ImportFormatReader.UnknownFormatImport unknownFormat = reader.importUnknownFormat(fileName); + ImportFormatReader.UnknownFormatImport unknownFormat = reader.importUnknownFormat(file); assertEquals(count, unknownFormat.parserResult.getDatabase().getEntryCount()); } @Test public void testImportFormatFromFile() throws IOException { - OutputPrinter nullPrinter = new OutputPrinterToNull(); - assertEquals(count, reader.importFromFile(format, fileName, nullPrinter).size()); + assertEquals(count, reader.importFromFile(format, file).getDatabase().getEntries().size()); } @Parameterized.Parameters(name = "{index}: {1}") diff --git a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java b/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java index 366cb3d0690f..1b071b4a14ed 100644 --- a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java +++ b/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java @@ -1,21 +1,22 @@ package net.sf.jabref.importer; -import static org.junit.Assert.*; - import java.io.IOException; -import java.util.List; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; -import org.junit.Before; -import org.junit.Test; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.model.entry.BibEntry; + +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; public class ImportFormatReaderTestParameterless { private ImportFormatReader reader; - private ImportFormatReader.UnknownFormatImport unknownFormat; - public List result; + @Before public void setUp() { Globals.prefs = JabRefPreferences.getInstance(); @@ -24,21 +25,21 @@ public void setUp() { } @Test - public void testImportUnknownFormatNotWorking() { - String fileName = ImportFormatReaderTestParameterless.class.getResource("fileformat/emptyFile.xml").getFile(); - unknownFormat = reader.importUnknownFormat(fileName); + public void testImportUnknownFormatNotWorking() throws URISyntaxException { + Path file = Paths.get(ImportFormatReaderTestParameterless.class.getResource("fileformat/emptyFile.xml").toURI()); + ImportFormatReader.UnknownFormatImport unknownFormat = reader.importUnknownFormat(file); assertNull(unknownFormat); } @Test(expected = NullPointerException.class) public void testNullImportUnknownFormat() { - unknownFormat = reader.importUnknownFormat(null); + reader.importUnknownFormat((Path)null); fail(); } @Test(expected = IllegalArgumentException.class) public void testImportFromFileUnknownFormat() throws IOException { - result = reader.importFromFile("someunknownformat", "doesn't matter", new OutputPrinterToNull()); + reader.importFromFile("someunknownformat", Paths.get("somepath")); fail(); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java index 347df5e61e19..4952671fd515 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java @@ -29,7 +29,7 @@ public void testGetFormatName() { @Test public void testGetCLIID() { BiblioscapeImporter importer = new BiblioscapeImporter(); - Assert.assertEquals(importer.getCLIId(), "biblioscape"); + Assert.assertEquals(importer.getId(), "biblioscape"); } @Test diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java index 9f3bf655215c..a34e125283bb 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java @@ -1,20 +1,19 @@ package net.sf.jabref.importer.fileformat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - import java.io.IOException; import java.io.InputStream; import java.util.List; -import org.junit.Before; -import org.junit.Test; - import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + /** * This class tests the BibtexImporter. * That importer is only used for --importToOpen, which is currently untested @@ -97,9 +96,4 @@ public void testImportEntries() throws IOException { public void testGetFormatName() { assertEquals("BibTeX", importer.getFormatName()); } - - @Test - public void testGetExtensions() { - assertEquals("bib", importer.getExtensions()); - } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index 07b90ef4f76c..8e7a8e88de07 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -34,7 +34,7 @@ public void testGetFormatName() { @Test public void testGetCLIId() { - assertEquals("refer", importer.getCLIId()); + assertEquals("refer", importer.getId()); } @Test diff --git a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java new file mode 100644 index 000000000000..2265ebf5b489 --- /dev/null +++ b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java @@ -0,0 +1,105 @@ +package net.sf.jabref.importer.fileformat; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import java.util.regex.Pattern; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.mockito.Mockito; +import static org.mockito.Mockito.when; + +@RunWith(Parameterized.class) +public class ImportFormatTest { + + @Parameter + public ImportFormat format; + + @Test(expected = NullPointerException.class) + public void isRecognizedFormatWithNullThrowsException() throws IOException { + format.isRecognizedFormat((InputStream)null); + } + + @Test(expected = NullPointerException.class) + public void importDatabaseWithNullThrowsException() throws IOException { + format.importDatabase((InputStream)null); + } + + @Test + public void importDatabaseWithUnrecognizedInputDoesNotReturnNull() throws IOException { + InputStream stream = new ByteArrayInputStream("!#!bad string".getBytes(StandardCharsets.UTF_8)); + Assert.assertNotNull(format.importDatabase(stream)); + } + + @Test + public void getFormatterNameDoesNotReturnNull() { + Assert.assertNotNull(format.getFormatName()); + } + + @Test + @Ignore + public void getExtensionsDoesNotReturnNull() { + Assert.assertNotNull(format.getExtensions()); + } + + @Test + public void getIdDoesNotReturnNull() { + Assert.assertNotNull(format.getId()); + } + + @Test + public void getIdDoesNotContainWhitespace() { + Pattern whitespacePattern = Pattern.compile("\\s"); + Assert.assertFalse(whitespacePattern.matcher(format.getId()).find()); + } + + @Test + public void getIdStripsSpecialCharactersAndConvertsToLowercase() { + ImportFormat importFormat = Mockito.mock(ImportFormat.class, Mockito.CALLS_REAL_METHODS); + when(importFormat.getFormatName()).thenReturn("*Test-Importer"); + Assert.assertEquals("testimporter", importFormat.getId()); + } + + @Test + @Ignore + public void getDescriptionDoesNotReturnNull() { + Assert.assertNotNull(format.getDescription()); + } + + @Parameters(name = "{index}: {0}") + public static Collection instancesToTest() { + // all classes implementing {@link ImportFormat} + // sorted alphabetically + + // @formatter:off + return Arrays.asList( + new Object[]{new BiblioscapeImporter()}, + new Object[]{new BibtexImporter()}, + new Object[]{new BibteXMLImporter()}, + new Object[]{new CopacImporter()}, + new Object[]{new EndnoteImporter()}, + new Object[]{new FreeCiteImporter()}, + new Object[]{new InspecImporter()}, + new Object[]{new IsiImporter()}, + new Object[]{new MedlineImporter()}, + new Object[]{new MedlinePlainImporter()}, + new Object[]{new MsBibImporter()}, + new Object[]{new OvidImporter()}, + new Object[]{new PdfContentImporter()}, + new Object[]{new PdfXmpImporter()}, + new Object[]{new RepecNepImporter()}, + new Object[]{new RisImporter()}, + new Object[]{new SilverPlatterImporter()} + ); + // @formatter:on + } +} \ No newline at end of file diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index 7b3ea9e5e259..b0ac44bfcb26 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -1,21 +1,22 @@ package net.sf.jabref.importer.fileformat; -import static org.junit.Assert.*; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class InspecImportTest { @@ -76,9 +77,11 @@ public void testCompleteBibtexEntryOnJournalPaperImport() throws IOException { public void importConferencePaperGivesInproceedings() throws IOException { String testInput = "Record.*INSPEC.*\n" + "\n" + - "RT ~ Conference-Paper"; + "RT ~ Conference-Paper\n" + + "AU ~ Prechelt, Lutz"; BibEntry shouldBeEntry = new BibEntry(); shouldBeEntry.setType("Inproceedings"); + shouldBeEntry.setField("author", "Prechelt, Lutz"); try (InputStream inStream = new ByteArrayInputStream(testInput.getBytes())) { List entries = inspecImp.importEntries(inStream, new OutputPrinterToNull()); @@ -92,9 +95,11 @@ public void importConferencePaperGivesInproceedings() throws IOException { public void importMiscGivesMisc() throws IOException { String testInput = "Record.*INSPEC.*\n" + "\n" + + "AU ~ Prechelt, Lutz \n" + "RT ~ Misc"; BibEntry shouldBeEntry = new BibEntry(); shouldBeEntry.setType("Misc"); + shouldBeEntry.setField("author", "Prechelt, Lutz"); try (InputStream inStream = new ByteArrayInputStream(testInput.getBytes())) { List entries = inspecImp.importEntries(inStream, new OutputPrinterToNull()); @@ -111,7 +116,7 @@ public void testGetFormatName() { @Test public void testGetCLIId() { - assertEquals("inspec", inspecImp.getCLIId()); + assertEquals("inspec", inspecImp.getId()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java index 1bd4dbef5b3a..1f4fbd991b9a 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java @@ -1,21 +1,22 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.*; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - /** * Test cases for the IsiImporter */ @@ -30,14 +31,6 @@ public static void setUp() { Globals.prefs = JabRefPreferences.getInstance(); } - @Test - public void testImportEntriesException() throws IOException { - thrown.expect(IOException.class); - - IsiImporter importer = new IsiImporter(); - importer.importEntries(null, new OutputPrinterToNull()); - } - @Test public void testParseMonthException() { IsiImporter.parseMonth("20l06 06-07"); @@ -54,7 +47,7 @@ public void testGetFormatName() { public void testGetCLIId() { IsiImporter importer = new IsiImporter(); - Assert.assertEquals(importer.getCLIId(), "isi"); + Assert.assertEquals(importer.getId(), "isi"); } @Test @@ -277,12 +270,6 @@ public void testIsiAuthorConvert() { Assert.assertEquals("", IsiImporter.isiAuthorConvert("")); } - @Test - public void testGetIsCustomImporter() { - IsiImporter importer = new IsiImporter(); - Assert.assertEquals(false, importer.isCustomImporter()); - } - @Test public void testImportIEEEExport() throws IOException { IsiImporter importer = new IsiImporter(); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index 7123a297c68c..579f81e637f4 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -8,16 +8,16 @@ import java.util.Collections; import java.util.List; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + public class MedlinePlainImporterTest { private final InputStream emptyFileStream = streamForString(""); @@ -99,12 +99,15 @@ public void testImportMultipleEntriesInSingleFile() throws IOException { Assert.assertEquals("inproceedings", testEntry.getType()); Assert.assertEquals("Inproceedings book title", testEntry.getField("booktitle")); - testEntry = entries.get(5); - Assert.assertEquals("proceedings", testEntry.getType()); - - testEntry = entries.get(6); - Assert.assertEquals("misc", testEntry.getType()); + BibEntry expectedEntry5 = new BibEntry(); + expectedEntry5.setType("proceedings"); + expectedEntry5.setField("keywords", "Female"); + BibtexEntryAssert.assertEquals(expectedEntry5, entries.get(5)); + BibEntry expectedEntry6 = new BibEntry(); + expectedEntry6.setType("misc"); + expectedEntry6.setField("keywords", "Female"); + BibtexEntryAssert.assertEquals(expectedEntry6, entries.get(6)); } } @@ -168,13 +171,17 @@ public void testKeyWords() throws IOException { @Test public void testAllArticleTypes() throws IOException { - try (InputStream stream = streamForString("PMID-22664795" + "\n" + "PT - journal article" + "\n" - + "PT - classical article" + "\n" + "PT - corrected and republished article" + "\n" - + "PT - introductory journal article" + "\n" + "PT - newspaper article");) { + try (InputStream stream = streamForString("PMID-22664795" + "\n" + + "MH - Female\n" + + "PT - journal article" + "\n" + + "PT - classical article" + "\n" + + "PT - corrected and republished article" + "\n" + + "PT - introductory journal article" + "\n" + "PT - newspaper article")) { List actualEntries = importer.importEntries(stream, new OutputPrinterToNull()); BibEntry expectedEntry = new BibEntry(); expectedEntry.setType("article"); + expectedEntry.setField("keywords", "Female"); BibtexEntryAssert.assertEquals(Arrays.asList(expectedEntry), actualEntries); } } @@ -186,7 +193,7 @@ public void testGetFormatName() { @Test public void testGetCLIId() { - Assert.assertEquals("medlineplain", importer.getCLIId()); + Assert.assertEquals("medlineplain", importer.getId()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java index 6d4a4a117f26..8b3c611a1936 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java @@ -62,7 +62,7 @@ public final void testGetFormatName() { @Test public final void testGetCommandLineId() { MsBibImporter testImporter = new MsBibImporter(); - Assert.assertEquals("msbib", testImporter.getCommandLineId()); + Assert.assertEquals("msbib", testImporter.getId()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index 14f6d99d6f1c..9a99b99b9914 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -34,7 +34,7 @@ public void testGetFormatName() { @Test public void testGetCLIId() { - Assert.assertEquals("ovid", importer.getCLIId()); + Assert.assertEquals("ovid", importer.getId()); } @Test diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index f8ed3673e3be..46c8c0b4d275 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -1,18 +1,23 @@ package net.sf.jabref.importer.fileformat; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; + import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.OutputPrinterToNull; -import net.sf.jabref.logic.xmp.EncryptedPdfsNotSupportedException; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; + +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.List; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class PdfXmpImporterTest { @@ -30,10 +35,11 @@ public void testGetFormatName() { assertEquals("XMP-annotated PDF", importer.getFormatName()); } - @Test(expected = EncryptedPdfsNotSupportedException.class) - public void importEncryptedFileThrowsException() throws IOException { + @Test + public void importEncryptedFileReturnsError() throws IOException { try (InputStream is = PdfXmpImporterTest.class.getResourceAsStream("/pdfs/encrypted.pdf")) { - importer.importEntries(is, new OutputPrinterToNull()); + ParserResult result = importer.importDatabase(is); + Assert.assertTrue(result.hasWarnings()); } } @@ -73,6 +79,6 @@ public void testIsRecognizedFormatReject() throws IOException { @Test public void testGetCommandLineId() { - assertEquals("xmp", importer.getCommandLineId()); + assertEquals("xmp", importer.getId()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java index 111af6384e0e..78e636ad76b8 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java @@ -27,7 +27,7 @@ public void testGetFormatName() { @Test public void testGetCLIId() { - Assert.assertEquals(risImporter.getCLIId(), "ris"); + Assert.assertEquals(risImporter.getId(), "ris"); } @Test diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index 72360cbf69e9..6543407440bd 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -5,15 +5,16 @@ import java.util.Arrays; import java.util.List; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + public class RepecNepImporterTest { private RepecNepImporter testImporter; @@ -47,11 +48,6 @@ public final void testIsNotRecognizedFormat() throws IOException { } } - @Test(expected = IOException.class) - public final void testImportEntriesNull() throws IOException { - testImporter.importEntries(null, new OutputPrinterToNull()); - } - @Test public final void testImportEntries1() throws IOException { try (InputStream in = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest1.txt"); @@ -90,7 +86,7 @@ public final void testGetFormatName() { @Test public final void testGetCliId() { - Assert.assertEquals("repecnep", testImporter.getCLIId()); + Assert.assertEquals("repecnep", testImporter.getId()); } @Test @@ -101,9 +97,4 @@ public final void testGetDescription() { + "copy&paste the papers you want to import and make sure, one of the first lines\n" + "contains the line \"nep.repec.org\".", testImporter.getDescription()); } - - @Test - public final void testGetExtensions() { - Assert.assertEquals(".txt", testImporter.getExtensions()); - } } diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestMultipleEntries.txt b/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestMultipleEntries.txt index 0f16addc6824..c9c85e07d32b 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestMultipleEntries.txt +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestMultipleEntries.txt @@ -94,6 +94,8 @@ JT - Inproceedings book title PMID-96578310 PT - Overall +MH - Female PMID-45984220 -PT - +PT - +MH - Female From a7508d20a2c07aff070b93ace75a5562f2336ff7 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 13 Apr 2016 22:12:59 +0200 Subject: [PATCH 003/268] Remove ImportFormat.importEntries --- .../jabref/importer/OutputPrinterToNull.java | 41 ---------------- .../importer/fetcher/MedlineFetcher.java | 17 ++++--- .../importer/fileformat/ImportFormat.java | 6 --- .../net/sf/jabref/pdfimport/PdfImporter.java | 48 ++++++++----------- .../fileformat/BiblioscapeImporterTest.java | 4 +- .../BiblioscapeImporterTestFiles.java | 5 +- .../BiblioscapeImporterTestTypes.java | 5 +- .../fileformat/BibtexImporterTest.java | 3 +- .../fileformat/CopacImporterTest.java | 5 +- .../fileformat/EndnoteImporterTest.java | 7 ++- .../importer/fileformat/InspecImportTest.java | 7 ++- .../importer/fileformat/IsiImporterTest.java | 17 ++++--- .../fileformat/MedlinePlainImporterTest.java | 13 +++-- .../fileformat/MsBibImporterTest.java | 9 ++-- .../fileformat/MsBibImporterTestfiles.java | 3 +- .../importer/fileformat/OvidImporterTest.java | 11 ++--- .../fileformat/PdfContentImporterTest.java | 2 +- .../PdfContentImporterTestFiles.java | 2 +- .../fileformat/PdfXmpImporterTest.java | 3 +- .../fileformat/RISImporterTestFiles.java | 3 +- .../fileformat/RepecNepImporterTest.java | 7 ++- .../fileformat/SilverPlatterImporterTest.java | 3 +- 22 files changed, 77 insertions(+), 144 deletions(-) delete mode 100644 src/main/java/net/sf/jabref/importer/OutputPrinterToNull.java diff --git a/src/main/java/net/sf/jabref/importer/OutputPrinterToNull.java b/src/main/java/net/sf/jabref/importer/OutputPrinterToNull.java deleted file mode 100644 index f9b2ab40b14f..000000000000 --- a/src/main/java/net/sf/jabref/importer/OutputPrinterToNull.java +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2011, 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.importer; - -/** - * Outputs nothing - * - * Used where really no output is desired - * - */ -public class OutputPrinterToNull implements OutputPrinter { - - @Override - public void setStatus(String s) { - // Do nothing - } - - @Override - public void showMessage(Object message, String title, int msgType) { - // Do nothing - } - - @Override - public void showMessage(String string) { - // Do nothing - } - -} diff --git a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java index 24d620362123..5b64c8f3476f 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java @@ -29,15 +29,16 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import net.sf.jabref.gui.help.HelpFiles; import net.sf.jabref.importer.ImportInspector; -import net.sf.jabref.importer.fileformat.MedlineImporter; import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.importer.fileformat.MedlineImporter; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.BibEntry; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * Fetch or search from Pubmed http://www.ncbi.nlm.nih.gov/sites/entrez/ @@ -237,7 +238,11 @@ private static List fetchMedline(String id, OutputPrinter status) { try { URL url = new URL(baseUrl); URLConnection data = url.openConnection(); - return new MedlineImporter().importEntries(data.getInputStream(), status); + ParserResult result = new MedlineImporter().importDatabase(data.getInputStream()); + if(result.hasWarnings()) { + status.showMessage(result.getErrorMessage()); + } + return result.getDatabase().getEntries(); } catch (IOException e) { return new ArrayList<>(); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java index fcc1cda2a3b1..7a57197ac4d8 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; @@ -87,11 +86,6 @@ public ParserResult importDatabase(Path filePath) throws IOException { } } - @Deprecated - public List importEntries(InputStream in, OutputPrinter printer) throws IOException { - return importDatabase(in).getDatabase().getEntries(); - } - /** * Returns the name of this import format. * diff --git a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java index 718c58c3f0f5..ae9f9db4778d 100644 --- a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java +++ b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java @@ -27,10 +27,6 @@ import javax.swing.JOptionPane; -import net.sf.jabref.model.entry.EntryType; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.DroppedFileHandler; @@ -41,13 +37,13 @@ import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.JabRefFrame; -import net.sf.jabref.gui.maintable.MainTable; import net.sf.jabref.gui.entryeditor.EntryEditor; +import net.sf.jabref.gui.maintable.MainTable; import net.sf.jabref.gui.preftabs.ImportSettingsTab; import net.sf.jabref.gui.undo.UndoableInsertEntry; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.PdfContentImporter; import net.sf.jabref.importer.fileformat.PdfXmpImporter; -import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.util.UpdateField; @@ -55,6 +51,11 @@ import net.sf.jabref.logic.xmp.XMPUtil; import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.IdGenerator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; public class PdfImporter { @@ -186,15 +187,19 @@ private List importPdfFiles(List fileNames) { } private void doXMPImport(String fileName, List res) { - BibEntry entry; List localRes = new ArrayList<>(); PdfXmpImporter importer = new PdfXmpImporter(); try (InputStream in = new FileInputStream(fileName)) { - localRes.addAll(importer.importEntries(in, frame)); + ParserResult result = importer.importDatabase(in); + if(result.hasWarnings()) { + frame.showMessage(result.getErrorMessage()); + } + localRes.addAll(result.getDatabase().getEntries()); } catch (IOException ex) { LOGGER.warn("Cannot import entries", ex); } + BibEntry entry; if (localRes.isEmpty()) { // import failed -> generate default entry LOGGER.info("Import failed"); @@ -234,9 +239,12 @@ private void doContentImport(String fileName, List res) { BibEntry entry; try (InputStream in = new FileInputStream(file)) { PdfContentImporter contentImporter = new PdfContentImporter(); - List localRes = contentImporter.importEntries(in, frame); + ParserResult result = contentImporter.importDatabase(in); + if(result.hasWarnings()) { + frame.showMessage(result.getErrorMessage()); + } - if (localRes.isEmpty()) { + if (!result.getDatabase().hasEntries()) { // import failed -> generate default entry entry = createNewBlankEntry(fileName); res.add(entry); @@ -244,7 +252,7 @@ private void doContentImport(String fileName, List res) { } // only one entry is imported - entry = localRes.get(0); + entry = result.getDatabase().getEntries().get(0); } catch (IOException e) { // import failed -> generate default entry LOGGER.info("Import failed", e); @@ -312,22 +320,4 @@ private BibEntry createNewEntry() { } return null; } - - public MainTable getEntryTable() { - return entryTable; - } - - public void setEntryTable(MainTable entryTable) { - this.entryTable = entryTable; - } - - public int getDropRow() { - return dropRow; - } - - public void setDropRow(int dropRow) { - this.dropRow = dropRow; - } - - } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java index 4952671fd515..b75e139fd189 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java @@ -5,7 +5,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -35,7 +35,7 @@ public void testGetCLIID() { @Test public void testImportEntriesAbortion() throws Throwable { try (InputStream is = BiblioscapeImporter.class.getResourceAsStream("BiblioscapeImporterTestCorrupt.txt")) { - Assert.assertEquals(Collections.emptyList(), bsImporter.importEntries(is, new OutputPrinterToNull())); + Assert.assertEquals(Collections.emptyList(), bsImporter.importDatabase(is).getDatabase().getEntries()); } } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java index ef88c7208f09..6edfccef8588 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java @@ -2,7 +2,6 @@ import net.sf.jabref.*; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; import org.junit.Before; @@ -58,11 +57,11 @@ public void testIsRecognizedFormat() throws IOException { public void testImportEntries() throws IOException { try (InputStream bsStream = BiblioscapeImporterTest.class.getResourceAsStream(fileName + ".txt")) { - List bsEntries = bsImporter.importEntries(bsStream, new OutputPrinterToNull()); + List bsEntries = bsImporter.importDatabase(bsStream).getDatabase().getEntries(); Assert.assertEquals(1, bsEntries.size()); BibtexEntryAssert.assertEquals(BiblioscapeImporterTest.class, fileName + ".bib", bsEntries); } } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java index e8660485ff6d..16ed3d3a152c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java @@ -10,7 +10,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -51,8 +50,8 @@ public void importConvertsToCorrectBibType() throws IOException { String bsInput = "--AU-- Baklouti, F.\n" + "--YP-- 1999\n" + "--KW-- Cells; Rna; Isoforms\n" + "--TI-- Blood\n" + "--RT-- " + biblioscapeType + "\n" + "------"; - List bibEntries = bsImporter.importEntries( - new ByteArrayInputStream(bsInput.getBytes(StandardCharsets.UTF_8)), new OutputPrinterToNull()); + List bibEntries = bsImporter.importDatabase( + new ByteArrayInputStream(bsInput.getBytes(StandardCharsets.UTF_8))).getDatabase().getEntries(); BibEntry entry = new BibEntry(); entry.setField("author", "Baklouti, F."); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java index a34e125283bb..4db2c2963820 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java @@ -6,7 +6,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Before; @@ -42,7 +41,7 @@ public void testIsRecognizedFormat() throws IOException { @Test public void testImportEntries() throws IOException { try (InputStream stream = BibtexImporterTest.class.getResourceAsStream("BibtexImporter.examples.bib")) { - List bibEntries = importer.importEntries(stream, new OutputPrinterToNull()); + List bibEntries = importer.importDatabase(stream).getDatabase().getEntries(); assertEquals(4, bibEntries.size()); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java index cfc1b6376b98..f293a60eb746 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java @@ -2,7 +2,6 @@ import net.sf.jabref.*; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; import org.junit.Before; @@ -56,7 +55,7 @@ public void testImportEntries() throws IOException { try (InputStream stream = CopacImporterTest.class .getResourceAsStream("CopacImporterTest1.txt")) { - List entries = importer.importEntries(stream, new OutputPrinterToNull()); + List entries = importer.importDatabase(stream).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibEntry entry = entries.get(0); @@ -77,7 +76,7 @@ public void testImportEntries2() throws IOException { try (InputStream stream = CopacImporterTest.class .getResourceAsStream("CopacImporterTest2.txt")) { - List entries = importer.importEntries(stream, new OutputPrinterToNull()); + List entries = importer.importDatabase(stream).getDatabase().getEntries(); Assert.assertEquals(2, entries.size()); BibEntry one = entries.get(0); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index 8e7a8e88de07..f059ae19686c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -2,7 +2,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Before; import org.junit.Test; @@ -64,7 +63,7 @@ public void testIsRecognizedFormatReject() throws IOException { @Test public void testImportEntries0() throws IOException { try (InputStream is = EndnoteImporterTest.class.getResourceAsStream("Endnote.entries.enw")) { - List bibEntries = importer.importEntries(is, new OutputPrinterToNull()); + List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); assertEquals(5, bibEntries.size()); @@ -111,7 +110,7 @@ public void testImportEntries0() throws IOException { public void testImportEntries1() throws IOException { String s = "%O Artn\\\\s testO\n%A testA,\n%E testE0, testE1"; InputStream is = new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)); - List bibEntries = importer.importEntries(is, new OutputPrinterToNull()); + List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); assertEquals(1, bibEntries.size()); @@ -125,7 +124,7 @@ public void testImportEntries1() throws IOException { @Test public void testImportEntriesBookExample() throws IOException { try (InputStream is = EndnoteImporterTest.class.getResourceAsStream("Endnote.book.example.enw")) { - List bibEntries = importer.importEntries(is, new OutputPrinterToNull()); + List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); assertEquals(1, bibEntries.size()); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index b0ac44bfcb26..309a18b1fef2 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -9,7 +9,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Before; @@ -65,7 +64,7 @@ public void testCompleteBibtexEntryOnJournalPaperImport() throws IOException { shouldBeEntry.setField("volume", "19"); try (InputStream inStream = InspecImportTest.class.getResourceAsStream("InspecImportTest2.txt")) { - List entries = inspecImp.importEntries(inStream, new OutputPrinterToNull()); + List entries = inspecImp.importDatabase(inStream).getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.get(0); BibtexEntryAssert.assertEquals(shouldBeEntry, entry); @@ -84,7 +83,7 @@ public void importConferencePaperGivesInproceedings() throws IOException { shouldBeEntry.setField("author", "Prechelt, Lutz"); try (InputStream inStream = new ByteArrayInputStream(testInput.getBytes())) { - List entries = inspecImp.importEntries(inStream, new OutputPrinterToNull()); + List entries = inspecImp.importDatabase(inStream).getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.get(0); BibtexEntryAssert.assertEquals(shouldBeEntry, entry); @@ -102,7 +101,7 @@ public void importMiscGivesMisc() throws IOException { shouldBeEntry.setField("author", "Prechelt, Lutz"); try (InputStream inStream = new ByteArrayInputStream(testInput.getBytes())) { - List entries = inspecImp.importEntries(inStream, new OutputPrinterToNull()); + List entries = inspecImp.importDatabase(inStream).getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.get(0); BibtexEntryAssert.assertEquals(shouldBeEntry, entry); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java index 1f4fbd991b9a..7218f6d9f640 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java @@ -8,7 +8,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -130,7 +129,7 @@ public void testImportEntries1() throws IOException { try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTest1.isi")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibEntry entry = entries.get(0); Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); @@ -153,7 +152,7 @@ public void testImportEntries2() throws IOException { try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTest2.isi")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(3, entries.size()); BibEntry entry = entries.get(0); Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); @@ -173,7 +172,7 @@ public void testImportEntriesINSPEC() throws IOException { try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestInspec.isi")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(2, entries.size()); BibEntry a = entries.get(0); @@ -215,7 +214,7 @@ public void testImportEntriesWOS() throws IOException { try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestWOS.isi")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(2, entries.size()); BibEntry a = entries.get(0); @@ -276,7 +275,7 @@ public void testImportIEEEExport() throws IOException { try (InputStream is = IsiImporterTest.class.getResourceAsStream("IEEEImport1.txt")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibEntry a = entries.get(0); @@ -304,7 +303,7 @@ public void testIEEEImport() throws IOException { try (InputStream is = IsiImporterTest.class.getResourceAsStream("IEEEImport1.txt")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibEntry a = entries.get(0); @@ -332,7 +331,7 @@ public void testImportEntriesMedline() throws IOException { IsiImporter importer = new IsiImporter(); try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestMedline.isi")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(2, entries.size()); BibEntry a = entries.get(0); @@ -371,7 +370,7 @@ public void testImportEntriesEmpty() throws IOException { try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestEmpty.isi")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index 579f81e637f4..9510b0b9760e 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -11,7 +11,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -68,7 +67,7 @@ public void testImportMultipleEntriesInSingleFile() throws IOException { try (InputStream is = MedlinePlainImporter.class .getResourceAsStream("MedlinePlainImporterTestMultipleEntries.txt")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(7, entries.size()); BibEntry testEntry = entries.get(0); @@ -113,7 +112,7 @@ public void testImportMultipleEntriesInSingleFile() throws IOException { @Test public void testEmptyFileImport() throws IOException { - List emptyEntries = importer.importEntries(emptyFileStream, new OutputPrinterToNull()); + List emptyEntries = importer.importDatabase(emptyFileStream).getDatabase().getEntries(); Assert.assertEquals(Collections.emptyList(), emptyEntries); } @@ -132,7 +131,7 @@ public void testImportSingleEntriesInSingleFiles() throws IOException { private void assertImportOfMedlineFileEqualsBibtexFile(String medlineFile, String bibtexFile) throws IOException { try (InputStream is = MedlinePlainImporter.class.getResourceAsStream(medlineFile); InputStream nis = MedlinePlainImporter.class.getResourceAsStream(bibtexFile)) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertNotNull(entries); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(nis, entries.get(0)); @@ -146,7 +145,7 @@ public void testMultiLineComments() throws IOException { + "\n" + "PRIN- Comment7" + "\n" + "PROF- Comment8" + "\n" + "RPI - Comment9" + "\n" + "RPF - Comment10" + "\n" + "RIN - Comment11" + "\n" + "ROF - Comment12" + "\n" + "UIN - Comment13" + "\n" + "UOF - Comment14" + "\n" + "SPIN- Comment15" + "\n" + "ORI - Comment16");) { - List actualEntries = importer.importEntries(stream, new OutputPrinterToNull()); + List actualEntries = importer.importDatabase(stream).getDatabase().getEntries(); BibEntry expectedEntry = new BibEntry(); expectedEntry.setField("comment", @@ -161,7 +160,7 @@ public void testMultiLineComments() throws IOException { @Test public void testKeyWords() throws IOException { try (InputStream stream = streamForString("PMID-22664795" + "\n" + "MH - Female" + "\n" + "OT - Male");) { - List actualEntries = importer.importEntries(stream, new OutputPrinterToNull()); + List actualEntries = importer.importDatabase(stream).getDatabase().getEntries(); BibEntry expectedEntry = new BibEntry(); expectedEntry.setField("keywords", "Female, Male"); @@ -177,7 +176,7 @@ public void testAllArticleTypes() throws IOException { "PT - classical article" + "\n" + "PT - corrected and republished article" + "\n" + "PT - introductory journal article" + "\n" + "PT - newspaper article")) { - List actualEntries = importer.importEntries(stream, new OutputPrinterToNull()); + List actualEntries = importer.importDatabase(stream).getDatabase().getEntries(); BibEntry expectedEntry = new BibEntry(); expectedEntry.setType("article"); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java index 8b3c611a1936..7c269aea5a13 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java @@ -12,7 +12,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; public class MsBibImporterTest { @@ -39,8 +38,8 @@ public final void testIsNotRecognizedFormat() throws Exception { public final void testImportEntriesEmpty() throws IOException { MsBibImporter testImporter = new MsBibImporter(); - List entries = testImporter.importEntries( - MsBibImporterTest.class.getResourceAsStream("MsBibImporterTest.xml"), new OutputPrinterToNull()); + List entries = testImporter.importDatabase( + MsBibImporterTest.class.getResourceAsStream("MsBibImporterTest.xml")).getDatabase().getEntries(); Assert.assertEquals(Collections.emptyList(), entries); } @@ -48,8 +47,8 @@ public final void testImportEntriesEmpty() throws IOException { public final void testImportEntriesNotRecognizedFormat() throws IOException { MsBibImporter testImporter = new MsBibImporter(); - List entries = testImporter.importEntries( - MsBibImporterTest.class.getResourceAsStream("CopacImporterTest1.txt"), new OutputPrinterToNull()); + List entries = testImporter.importDatabase( + MsBibImporterTest.class.getResourceAsStream("CopacImporterTest1.txt")).getDatabase().getEntries(); Assert.assertEquals(0, entries.size()); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java index 35e3e9204b72..cf6b56ee1769 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java @@ -16,7 +16,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; @RunWith(Parameterized.class) @@ -55,7 +54,7 @@ public void testImportEntries() throws IOException { String bibFileName = fileName + ".bib"; MsBibImporter testImporter = new MsBibImporter(); try (InputStream is = MsBibImporter.class.getResourceAsStream(xmlFileName)) { - List result = testImporter.importEntries(is, new OutputPrinterToNull()); + List result = testImporter.importDatabase(is).getDatabase().getEntries(); BibtexEntryAssert.assertEquals(MsBibImporterTest.class, bibFileName, result); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index 9a99b99b9914..b156b4a6685d 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -13,7 +13,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; public class OvidImporterTest { @@ -66,7 +65,7 @@ public void testIsRecognizedFormatRejected() throws IOException { public void testImportEmpty() throws IOException { try (InputStream is = OvidImporter.class.getResourceAsStream("Empty.txt")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(Collections.emptyList(), entries); } } @@ -75,7 +74,7 @@ public void testImportEmpty() throws IOException { public void testImportEntries1() throws IOException { try (InputStream is = OvidImporter.class.getResourceAsStream("OvidImporterTest1.txt")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(5, entries.size()); BibEntry entry = entries.get(0); @@ -130,7 +129,7 @@ public void testImportEntries1() throws IOException { public void testImportEntries2() throws IOException { try (InputStream is = OvidImporter.class.getResourceAsStream("OvidImporterTest2.txt")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertEquals(Collections.emptyList(), entries); } } @@ -141,11 +140,11 @@ public void testImportSingleEntries() throws IOException { for (int n = 3; n <= 7; n++) { try (InputStream is = OvidImporter.class.getResourceAsStream("OvidImporterTest" + n + ".txt"); InputStream nis = OvidImporter.class.getResourceAsStream("OvidImporterTestBib" + n + ".bib")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); + List entries = importer.importDatabase(is).getDatabase().getEntries(); Assert.assertNotNull(entries); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(nis, entries.get(0)); } } } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java index 5a1b5f18cb34..2ec3d8d14e6f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java @@ -17,7 +17,7 @@ public class PdfContentImporterTest { public void doesNotHandleEncryptedPdfs() throws IOException { PdfContentImporter importer = new PdfContentImporter(); try (InputStream is = PdfContentImporter.class.getResourceAsStream("/pdfs/encrypted.pdf")) { - List result = importer.importEntries(is, null); + List result = importer.importDatabase(is).getDatabase().getEntries(); assertEquals(Collections.emptyList(), result); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java index 83735066b7bd..c562b75dd5f4 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java @@ -48,7 +48,7 @@ public void correctContent() throws IOException { String bibFileName = fileName + ".bib"; PdfContentImporter importer = new PdfContentImporter(); try (InputStream is = PdfContentImporter.class.getResourceAsStream(pdfFileName)) { - List result = importer.importEntries(is, null); + List result = importer.importDatabase(is).getDatabase().getEntries(); BibtexEntryAssert.assertEquals(PdfContentImporterTest.class, bibFileName, result); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index 46c8c0b4d275..23cc6f3240bc 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -7,7 +7,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; @@ -46,7 +45,7 @@ public void importEncryptedFileReturnsError() throws IOException { @Test public void testImportEntries() throws IOException { try (InputStream is = PdfXmpImporterTest.class.getResourceAsStream("annotated.pdf")) { - List bibEntries = importer.importEntries(is, new OutputPrinterToNull()); + List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); assertEquals(1, bibEntries.size()); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java index d4ec8ddc93a2..290a6e06f41b 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java @@ -2,7 +2,6 @@ import net.sf.jabref.*; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; import org.junit.Before; @@ -51,7 +50,7 @@ public void testIsRecognizedFormat() throws IOException { public void testImportEntries() throws IOException { try (InputStream risStream = RISImporterTest.class.getResourceAsStream(fileName + ".ris")) { - List risEntries = risImporter.importEntries(risStream, new OutputPrinterToNull()); + List risEntries = risImporter.importDatabase(risStream).getDatabase().getEntries(); BibtexEntryAssert.assertEquals(RISImporterTest.class, fileName + ".bib", risEntries); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index 6543407440bd..30cb24a1e2ea 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -8,7 +8,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -52,7 +51,7 @@ public final void testIsNotRecognizedFormat() throws IOException { public final void testImportEntries1() throws IOException { try (InputStream in = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest1.txt"); InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest1.bib")) { - List entries = testImporter.importEntries(in, new OutputPrinterToNull()); + List entries = testImporter.importDatabase(in).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(bibIn, entries.get(0)); } @@ -62,7 +61,7 @@ public final void testImportEntries1() throws IOException { public final void testImportEntries2() throws IOException { try (InputStream in = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest2.txt"); InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest2.bib")) { - List entries = testImporter.importEntries(in, new OutputPrinterToNull()); + List entries = testImporter.importDatabase(in).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(bibIn, entries.get(0)); } @@ -72,7 +71,7 @@ public final void testImportEntries2() throws IOException { public final void testImportEntries3() throws IOException { try (InputStream in = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest3.txt"); InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest3.bib")) { - List entries = testImporter.importEntries(in, new OutputPrinterToNull()); + List entries = testImporter.importDatabase(in).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(bibIn, entries.get(0)); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java index e5887e634695..e1d459716a92 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java @@ -16,7 +16,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; @RunWith(Parameterized.class) @@ -56,7 +55,7 @@ public final void testIsRecognizedFormat() throws Exception { public final void testImportEntries() throws Exception { try (InputStream in = SilverPlatterImporter.class.getResourceAsStream(txtName); InputStream bibIn = SilverPlatterImporterTest.class.getResourceAsStream(bibName)) { - List entries = testImporter.importEntries(in, new OutputPrinterToNull()); + List entries = testImporter.importDatabase(in).getDatabase().getEntries(); BibtexEntryAssert.assertEquals(bibIn, entries); } } From 4425551f3372e5c5e46ae841af75289184f2b94a Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 14 Apr 2016 12:36:11 +0200 Subject: [PATCH 004/268] ImportFormat use Reader instead of InputStream --- .../jabref/importer/ImportFormatReader.java | 6 +- .../importer/fetcher/MedlineFetcher.java | 5 +- .../fileformat/BiblioscapeImporter.java | 17 +- .../importer/fileformat/BibteXMLImporter.java | 26 +- .../importer/fileformat/BibtexImporter.java | 11 +- .../importer/fileformat/CopacImporter.java | 49 ++- .../importer/fileformat/EndnoteImporter.java | 44 +-- .../importer/fileformat/FreeCiteImporter.java | 10 +- .../importer/fileformat/ImportFormat.java | 36 +- .../importer/fileformat/InspecImporter.java | 37 +- .../importer/fileformat/IsiImporter.java | 86 ++--- .../importer/fileformat/MedlineImporter.java | 37 +- .../fileformat/MedlinePlainImporter.java | 29 +- .../importer/fileformat/MsBibImporter.java | 15 +- .../importer/fileformat/OvidImporter.java | 37 +- .../fileformat/PdfContentImporter.java | 20 +- .../importer/fileformat/PdfXmpImporter.java | 32 +- .../importer/fileformat/RepecNepImporter.java | 56 +-- .../importer/fileformat/RisImporter.java | 33 +- .../fileformat/SilverPlatterImporter.java | 247 +++++++------ .../sf/jabref/logic/msbib/MSBibDatabase.java | 13 +- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 12 +- .../net/sf/jabref/pdfimport/PdfImporter.java | 47 +-- .../fileformat/BiblioscapeImporterTest.java | 10 +- .../BiblioscapeImporterTestFiles.java | 49 +-- .../BiblioscapeImporterTestTypes.java | 8 +- .../fileformat/BibtexImporterTest.java | 102 +++--- .../fileformat/CopacImporterTest.java | 96 +++-- .../fileformat/EndnoteImporterTest.java | 159 ++++---- .../importer/fileformat/ImportFormatTest.java | 16 +- .../importer/fileformat/InspecImportTest.java | 45 +-- .../importer/fileformat/IsiImporterTest.java | 338 ++++++++---------- .../fileformat/MedlinePlainImporterTest.java | 171 ++++----- .../fileformat/MsBibImporterTest.java | 33 +- .../fileformat/MsBibImporterTestfiles.java | 35 +- .../importer/fileformat/OvidImporterTest.java | 156 ++++---- .../fileformat/PdfContentImporterTest.java | 24 +- .../PdfContentImporterTestFiles.java | 24 +- .../fileformat/PdfXmpImporterTest.java | 47 ++- .../importer/fileformat/RISImporterTest.java | 17 +- .../fileformat/RISImporterTestFiles.java | 40 +-- .../fileformat/RepecNepImporterTest.java | 42 +-- .../fileformat/SilverPlatterImporterTest.java | 26 +- ...ilverPlatterImporterTestNotRecognized.java | 15 +- 44 files changed, 1157 insertions(+), 1201 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java index ef5336cdbf65..c0b4b1fcaeec 100644 --- a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java +++ b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java @@ -137,11 +137,11 @@ public ParserResult importFromFile(ImportFormat importer, Path file) throws IOEx Objects.requireNonNull(importer); Objects.requireNonNull(file); - if(!importer.isRecognizedFormat(file)) { + if(!importer.isRecognizedFormat(file, Globals.prefs.getDefaultEncoding())) { throw new IOException("Wrong file format"); } - return importer.importDatabase(file); + return importer.importDatabase(file, Globals.prefs.getDefaultEncoding()); } /** @@ -253,7 +253,7 @@ public UnknownFormatImport importUnknownFormat(Path file) { // Cycle through all importers: for (ImportFormat imFo : getImportFormats()) { try { - if(!imFo.isRecognizedFormat(file)) { + if(!imFo.isRecognizedFormat(file, Globals.prefs.getDefaultEncoding())) { continue; } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java index 5b64c8f3476f..683d51393e22 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java @@ -238,8 +238,9 @@ private static List fetchMedline(String id, OutputPrinter status) { try { URL url = new URL(baseUrl); URLConnection data = url.openConnection(); - ParserResult result = new MedlineImporter().importDatabase(data.getInputStream()); - if(result.hasWarnings()) { + ParserResult result = new MedlineImporter().importDatabase( + new BufferedReader(new InputStreamReader(data.getInputStream()))); + if (result.hasWarnings()) { status.showMessage(result.getErrorMessage()); } return result.getDatabase().getEntries(); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java index 5d768b61def0..29b8d4290c6b 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java @@ -17,10 +17,12 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; @@ -48,21 +50,20 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream in) { - Objects.requireNonNull(in); + public boolean isRecognizedFormat(BufferedReader reader) { + Objects.requireNonNull(reader); return true; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { + public ParserResult importDatabase(BufferedReader reader) throws IOException { List bibItems = new ArrayList<>(); - BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream)); String line; Map hm = new HashMap<>(); Map lines = new HashMap<>(); StringBuilder previousLine = null; - while ((line = in.readLine()) != null) { + while ((line = reader.readLine()) != null) { if (line.isEmpty()) { continue; // ignore empty lines, e.g. at file } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java index a7969758f83c..bed0976f6f82 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibteXMLImporter.java @@ -17,19 +17,20 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.regex.Pattern; + import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.xml.sax.InputSource; /** * Importer for the Refer/Endnote format. @@ -59,23 +60,20 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { - + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { // Our strategy is to look for the " bibItems = new ArrayList<>(); @@ -91,7 +89,7 @@ public ParserResult importDatabase(InputStream stream) throws IOException { SAXParser parser = parserFactory.newSAXParser(); //May throw exceptions BibTeXMLHandler handler = new BibTeXMLHandler(); // Start the parser. It reads the file and calls methods of the handler. - parser.parse(stream, handler); + parser.parse(new InputSource(reader), handler); // When you're done, report the results stored by your handler object bibItems.addAll(handler.getItems()); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java index a0822c906bc6..9ec223becdfb 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java @@ -15,13 +15,12 @@ */ package net.sf.jabref.importer.fileformat; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Objects; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; /** @@ -37,14 +36,14 @@ public class BibtexImporter extends ImportFormat { * https://github.com/JabRef/jabref/pull/379#issuecomment-158685726 for more details. */ @Override - public boolean isRecognizedFormat(InputStream in) { - Objects.requireNonNull(in); + public boolean isRecognizedFormat(BufferedReader reader) { + Objects.requireNonNull(reader); return true; } @Override - public ParserResult importDatabase(InputStream in) throws IOException { - return BibtexParser.parse(ImportFormatReader.getReaderDefaultEncoding(in)); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + return BibtexParser.parse(reader); } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java index 4d0d5d78addb..6a058417fc8c 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java @@ -17,13 +17,11 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; @@ -59,53 +57,46 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { - - BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream)); - + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { String str; - - while ((str = in.readLine()) != null) { + while ((str = reader.readLine()) != null) { if (CopacImporter.COPAC_PATTERN.matcher(str).find()) { return true; } } - return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { - Objects.requireNonNull(stream); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); List entries = new LinkedList<>(); StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - // Preprocess entries - String str; + // Preprocess entries + String str; - while ((str = in.readLine()) != null) { + while ((str = reader.readLine()) != null) { - if (str.length() < 4) { - continue; - } + if (str.length() < 4) { + continue; + } - String code = str.substring(0, 4); + String code = str.substring(0, 4); - if (" ".equals(code)) { - sb.append(' ').append(str.trim()); - } else { + if (" ".equals(code)) { + sb.append(' ').append(str.trim()); + } else { - // begining of a new item - if ("TI- ".equals(str.substring(0, 4))) { - if (sb.length() > 0) { - entries.add(sb.toString()); - } - sb = new StringBuilder(); + // begining of a new item + if ("TI- ".equals(str.substring(0, 4))) { + if (sb.length() > 0) { + entries.add(sb.toString()); } - sb.append('\n').append(str); + sb = new StringBuilder(); } + sb.append('\n').append(str); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java index a4445eff3190..1f5b87746036 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java @@ -17,13 +17,11 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.model.entry.AuthorList; @@ -65,42 +63,36 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { - + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { // Our strategy is to look for the "%A *" line. - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String str; - while ((str = in.readLine()) != null) { - if (A_PATTERN.matcher(str).matches() || E_PATTERN.matcher(str).matches()) { - return true; - } + String str; + while ((str = reader.readLine()) != null) { + if (A_PATTERN.matcher(str).matches() || E_PATTERN.matcher(str).matches()) { + return true; } } return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { + public ParserResult importDatabase(BufferedReader reader) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - - String str; - boolean first = true; - while ((str = in.readLine()) != null) { - str = str.trim(); - if (str.indexOf("%0") == 0) { - if (first) { - first = false; - } else { - sb.append(ENDOFRECORD); - } - sb.append(str); + String str; + boolean first = true; + while ((str = reader.readLine()) != null) { + str = str.trim(); + if (str.indexOf("%0") == 0) { + if (first) { + first = false; } else { - sb.append(str); + sb.append(ENDOFRECORD); } - sb.append('\n'); + sb.append(str); + } else { + sb.append(str); } + sb.append('\n'); } String[] entries = sb.toString().split(ENDOFRECORD); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index ceadc4dd59b5..a52b980c4f82 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -15,8 +15,8 @@ */ package net.sf.jabref.importer.fileformat; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; @@ -55,16 +55,16 @@ public class FreeCiteImporter extends ImportFormat { private static final Log LOGGER = LogFactory.getLog(FreeCiteImporter.class); @Override - public boolean isRecognizedFormat(InputStream in) throws IOException { - Objects.requireNonNull(in); + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); // TODO: We don't know how to recognize text files, therefore we return "false" return false; } @Override - public ParserResult importDatabase(InputStream in) + public ParserResult importDatabase(BufferedReader reader) throws IOException { - try (Scanner scan = new Scanner(in)) { + try (Scanner scan = new Scanner(reader)) { String text = scan.useDelimiter("\\A").next(); return importEntries(text); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java index 7a57197ac4d8..2c50926da2d5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java @@ -15,16 +15,17 @@ */ package net.sf.jabref.importer.fileformat; -import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; import java.nio.file.Path; import java.util.List; import java.util.Objects; import net.sf.jabref.importer.ParserResult; -import net.sf.jabref.model.entry.BibEntry; /** * Role of an importer for JabRef. @@ -49,15 +50,13 @@ public abstract class ImportFormat implements Comparable { * Thus the correct behaviour is to return false if it is certain that the file is * not of the suitable type, and true otherwise. Returning true is the safe choice if not certain. */ - public abstract boolean isRecognizedFormat(InputStream in) throws IOException; + protected abstract boolean isRecognizedFormat(BufferedReader input) throws IOException; - public boolean isRecognizedFormat(Path filePath) throws IOException { + public boolean isRecognizedFormat(Path filePath, Charset defaultEncoding) throws IOException { try (InputStream stream = new FileInputStream(filePath.toFile()); - BufferedInputStream bufferedStream = new BufferedInputStream(stream)) { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, defaultEncoding))) { - bufferedStream.mark(Integer.MAX_VALUE); - - return isRecognizedFormat(bufferedStream); + return isRecognizedFormat(bufferedReader); } } @@ -74,15 +73,24 @@ public boolean isRecognizedFormat(Path filePath) throws IOException { * * This method should never return null. * - * @param in the input stream to read from + * @param input the input to read from */ - public abstract ParserResult importDatabase(InputStream in) throws IOException ; + protected abstract ParserResult importDatabase(BufferedReader input) throws IOException ; - public ParserResult importDatabase(Path filePath) throws IOException { + /** + * Parse the database in the specified file. + * + * Importer having the facilities to detect the correct encoding of a file should overwrite this method, + * determine the encoding and then call {@link #importDatabase(BufferedReader)}. + * + * @param filePath the path to the file which should be imported + * @param defaultEncoding the encoding used by default to decode the file + */ + public ParserResult importDatabase(Path filePath, Charset defaultEncoding) throws IOException { try (InputStream stream = new FileInputStream(filePath.toFile()); - BufferedInputStream bufferedStream = new BufferedInputStream(stream)) { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, defaultEncoding))) { - return importDatabase(bufferedStream); + return importDatabase(bufferedReader); } } @@ -128,7 +136,7 @@ public String getId() { *

    • * what kind of entries from what sources and based on what specification it is able to import *
    • - * by what criteria it {@link #isRecognizedFormat(InputStream) recognizes} an import format + * by what criteria it {@link #isRecognizedFormat(BufferedReader) recognizes} an import format *
    * * @return description of the import format diff --git a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java index efffc671eb80..f60bad7fe4e3 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java @@ -17,14 +17,12 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -52,35 +50,30 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { // Our strategy is to look for the "PY " line. - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String str; - - while ((str = in.readLine()) != null) { - if (INSPEC_PATTERN.matcher(str).find()) { - return true; - } + String str; + while ((str = reader.readLine()) != null) { + if (INSPEC_PATTERN.matcher(str).find()) { + return true; } } return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { + public ParserResult importDatabase(BufferedReader reader) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String str; - while ((str = in.readLine()) != null) { - if (str.length() < 2) { - continue; - } - if (str.indexOf("Record") == 0) { - sb.append("__::__").append(str); - } else { - sb.append("__NEWFIELD__").append(str); - } + String str; + while ((str = reader.readLine()) != null) { + if (str.length() < 2) { + continue; + } + if (str.indexOf("Record") == 0) { + sb.append("__::__").append(str); + } else { + sb.append("__NEWFIELD__").append(str); } } String[] entries = sb.toString().split("__::__"); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java index eae142a0cf4e..29a5439bdf3e 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java @@ -17,7 +17,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -26,7 +25,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.formatter.CaseChangers; import net.sf.jabref.model.entry.BibEntry; @@ -79,27 +77,23 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { - - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - - String str; - int i = 0; - while (((str = in.readLine()) != null) && (i < 50)) { - - /** - * The following line gives false positives for RIS files, so it - * should not be uncommented. The hypen is a characteristic of the - * RIS format. - * - * str = str.replace(" - ", "") - */ - if (IsiImporter.ISI_PATTERN.matcher(str).find()) { - return true; - } - - i++; + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { + String str; + int i = 0; + while (((str = reader.readLine()) != null) && (i < 50)) { + + /** + * The following line gives false positives for RIS files, so it + * should not be uncommented. The hypen is a characteristic of the + * RIS format. + * + * str = str.replace(" - ", "") + */ + if (IsiImporter.ISI_PATTERN.matcher(str).find()) { + return true; } + + i++; } return false; } @@ -153,38 +147,36 @@ private static void processCapitalization(Map map) { } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { - Objects.requireNonNull(stream); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - // Pattern fieldPattern = Pattern.compile("^AU |^TI |^SO |^DT |^C1 |^AB - // |^ID |^BP |^PY |^SE |^PY |^VL |^IS "); - String str; + // Pattern fieldPattern = Pattern.compile("^AU |^TI |^SO |^DT |^C1 |^AB + // |^ID |^BP |^PY |^SE |^PY |^VL |^IS "); + String str; - while ((str = in.readLine()) != null) { - if (str.length() < 3) { - continue; - } + while ((str = reader.readLine()) != null) { + if (str.length() < 3) { + continue; + } - // beginning of a new item - if ("PT ".equals(str.substring(0, 3))) { - sb.append("::").append(str); + // beginning of a new item + if ("PT ".equals(str.substring(0, 3))) { + sb.append("::").append(str); + } else { + String beg = str.substring(0, 3).trim(); + + // I could have used the fieldPattern regular expression instead + // however this seems to be + // quick and dirty and it works! + if (beg.length() == 2) { + sb.append(" ## "); // mark the beginning of each field + sb.append(str); } else { - String beg = str.substring(0, 3).trim(); - - // I could have used the fieldPattern regular expression instead - // however this seems to be - // quick and dirty and it works! - if (beg.length() == 2) { - sb.append(" ## "); // mark the beginning of each field - sb.append(str); - } else { - sb.append("EOLEOL"); // mark the end of each line - sb.append(str.trim()); // remove the initial spaces - } + sb.append("EOLEOL"); // mark the end of each line + sb.append(str.trim()); // remove the initial spaces } } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java index 1d849ffce803..4a27483d3cc1 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java @@ -15,7 +15,10 @@ */ package net.sf.jabref.importer.fileformat; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -23,11 +26,12 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.xml.sax.InputSource; /** * Importer for the Refer/Endnote format. @@ -61,26 +65,23 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { - - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String str; - int i = 0; - while (((str = in.readLine()) != null) && (i < 50)) { + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { + String str; + int i = 0; + while (((str = reader.readLine()) != null) && (i < 50)) { - if (str.toLowerCase().contains("")) { - return true; - } - - i++; + if (str.toLowerCase().contains("")) { + return true; } + + i++; } return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { - Objects.requireNonNull(stream); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); // Obtain a factory object for creating SAX parsers SAXParserFactory parserFactory = SAXParserFactory.newInstance(); @@ -98,14 +99,14 @@ public ParserResult importDatabase(InputStream stream) throws IOException { MedlineHandler handler = new MedlineHandler(); // Start the parser. It reads the file and calls methods of the // handler. - parser.parse(stream, handler); + parser.parse(new InputSource(reader), handler); // Switch this to true if you want to make a local copy for testing. if (false) { - stream.reset(); + reader.reset(); try (FileOutputStream out = new FileOutputStream(new File("/home/alver/ut.txt"))) { int c; - while ((c = stream.read()) != -1) { + while ((c = reader.read()) != -1) { out.write((char) c); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index 5e17ad000754..6fbb3a1fead8 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -19,14 +19,12 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -61,33 +59,28 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { // Our strategy is to look for the "PMID - *", "PMC.*-.*", or "PMCR.*-.*" line // (i.e., PubMed Unique Identifier, PubMed Central Identifier, PubMed Central Release) - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - - String str; - while ((str = in.readLine()) != null) { - if (PMID_PATTERN.matcher(str).find() || PMC_PATTERN.matcher(str).find() - || PMCR_PATTERN.matcher(str).find()) { - return true; - } + String str; + while ((str = reader.readLine()) != null) { + if (PMID_PATTERN.matcher(str).find() || PMC_PATTERN.matcher(str).find() || PMCR_PATTERN.matcher(str) + .find()) { + return true; } } return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { + public ParserResult importDatabase(BufferedReader reader) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String str; - while ((str = in.readLine()) != null) { - sb.append(str); - sb.append('\n'); - } + String str; + while ((str = reader.readLine()) != null) { + sb.append(str); + sb.append('\n'); } String[] entries = sb.toString().replace("\u2013", "-").replace("\u2014", "--").replace("\u2015", "--") .split("\\n\\n"); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java index c92503c7be59..52d11a7a5d80 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java @@ -15,8 +15,8 @@ */ package net.sf.jabref.importer.fileformat; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.List; import java.util.Objects; @@ -27,6 +27,7 @@ import net.sf.jabref.logic.msbib.MSBibDatabase; import org.w3c.dom.Document; +import org.xml.sax.InputSource; /** * Importer for the MS Office 2007 XML bibliography format @@ -37,8 +38,8 @@ public class MsBibImporter extends ImportFormat { @Override - public boolean isRecognizedFormat(InputStream in) throws IOException { - Objects.requireNonNull(in); + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); /* The correct behaviour is to return false if it is certain that the file is @@ -50,7 +51,7 @@ public boolean isRecognizedFormat(InputStream in) throws IOException { DocumentBuilder dbuild = DocumentBuilderFactory. newInstance(). newDocumentBuilder(); - docin = dbuild.parse(in); + docin = dbuild.parse(new InputSource(reader)); } catch (Exception e) { return false; } @@ -58,11 +59,11 @@ public boolean isRecognizedFormat(InputStream in) throws IOException { } @Override - public ParserResult importDatabase(InputStream in) throws IOException { - Objects.requireNonNull(in); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); MSBibDatabase dbase = new MSBibDatabase(); - return new ParserResult(dbase.importEntries(in)); + return new ParserResult(dbase.importEntries(reader)); } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java index c922e3484f9f..de8fe3d3201e 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java @@ -17,7 +17,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -25,7 +24,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -72,36 +70,31 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { + String str; + int i = 0; + while (((str = reader.readLine()) != null) && (i < MAX_ITEMS)) { - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String str; - int i = 0; - while (((str = in.readLine()) != null) && (i < MAX_ITEMS)) { - - if (OvidImporter.OVID_PATTERN.matcher(str).find()) { - return true; - } - - i++; + if (OvidImporter.OVID_PATTERN.matcher(str).find()) { + return true; } + + i++; } return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { + public ParserResult importDatabase(BufferedReader reader) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String line; - while ((line = in.readLine()) != null) { - if (!line.isEmpty() && (line.charAt(0) != ' ')) { - sb.append("__NEWFIELD__"); - } - sb.append(line); - sb.append('\n'); + String line; + while ((line = reader.readLine()) != null) { + if (!line.isEmpty() && (line.charAt(0) != ' ')) { + sb.append("__NEWFIELD__"); } + sb.append(line); + sb.append('\n'); } String[] items = sb.toString().split(OVID_PATTERN_STRING); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index b93460ff0e19..a9a412ee9755 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -1,8 +1,10 @@ package net.sf.jabref.importer.fileformat; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -175,17 +177,23 @@ private static String streamlineTitle(String title) { } @Override - public boolean isRecognizedFormat(InputStream in) throws IOException { - Objects.requireNonNull(in); + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); return false; } @Override - public ParserResult importDatabase(InputStream in) throws IOException { - Objects.requireNonNull(in); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); + throw new UnsupportedOperationException( + "PdfContentImporter does not support importDatabase(BufferedReader reader)." + + "Instead use importDatabase(Path filePath, Charset defaultEncoding)."); + } + @Override + public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { final ArrayList result = new ArrayList<>(1); - try (PDDocument document = XMPUtil.loadWithAutomaticDecryption(in)) { + try (PDDocument document = XMPUtil.loadWithAutomaticDecryption(filePath)) { String firstPageContents = getFirstPageContents(document); Optional doi = DOI.findInText(firstPageContents); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java index 1dc8fd50aab2..14bb88b624c5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java @@ -15,8 +15,10 @@ */ package net.sf.jabref.importer.fileformat; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -40,23 +42,39 @@ public List getExtensions() { } @Override - public ParserResult importDatabase(InputStream in) throws IOException { - Objects.requireNonNull(in); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); + throw new UnsupportedOperationException( + "PdfXmpImporter does not support importDatabase(BufferedReader reader)." + + "Instead use importDatabase(Path filePath, Charset defaultEncoding)."); + } + + @Override + public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { + Objects.requireNonNull(filePath); try { - return new ParserResult(XMPUtil.readXMP(in)); + return new ParserResult(XMPUtil.readXMP(filePath)); } catch (IOException exception) { return ParserResult.fromErrorMessage(exception.getLocalizedMessage()); } } + @Override + protected boolean isRecognizedFormat(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); + throw new UnsupportedOperationException( + "PdfXmpImporter does not support isRecognizedFormat(BufferedReader reader)." + + "Instead use isRecognizedFormat(Path filePath, Charset defaultEncoding)."); + } + /** * Returns whether the given stream contains data that is a.) a pdf and b.) * contains at least one BibEntry. */ @Override - public boolean isRecognizedFormat(InputStream in) throws IOException { - Objects.requireNonNull(in); - return XMPUtil.hasMetadata(in); + public boolean isRecognizedFormat(Path filePath, Charset defaultEncoding) throws IOException { + Objects.requireNonNull(filePath); + return XMPUtil.hasMetadata(filePath); } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index c7cd78f99f23..04871c5d41e5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -19,15 +19,22 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Objects; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -188,20 +195,18 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { // read the first couple of lines // NEP message usually contain the String 'NEP: New Economics Papers' // or, they are from nep.repec.org - try (BufferedReader inBR = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - StringBuilder startOfMessage = new StringBuilder(); - String tmpLine = inBR.readLine(); - for (int i = 0; (i < 25) && (tmpLine != null); i++) { - startOfMessage.append(tmpLine); - tmpLine = inBR.readLine(); - } - return startOfMessage.toString().contains("NEP: New Economics Papers") - || startOfMessage.toString().contains("nep.repec.org"); + StringBuilder startOfMessage = new StringBuilder(); + String tmpLine = reader.readLine(); + for (int i = 0; (i < 25) && (tmpLine != null); i++) { + startOfMessage.append(tmpLine); + tmpLine = reader.readLine(); } + return startOfMessage.toString().contains("NEP: New Economics Papers") || startOfMessage.toString().contains( + "nep.repec.org"); } private boolean startsWithKeyword(Collection keywords) { @@ -408,15 +413,14 @@ private boolean isStartOfWorkingPaper() { } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { - Objects.requireNonNull(stream); + public ParserResult importDatabase(BufferedReader reader) throws IOException { + Objects.requireNonNull(reader); List bibitems = new ArrayList<>(); String paperNoStr = null; this.line = 0; - - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - readLine(in); // skip header and editor information + try { + readLine(reader); // skip header and editor information while (this.lastLine != null) { if (this.lastLine.startsWith("-----------------------------")) { @@ -426,25 +430,25 @@ public ParserResult importDatabase(InputStream stream) throws IOException { BibEntry be = new BibEntry(IdGenerator.next()); be.setType("techreport"); paperNoStr = this.lastLine.substring(0, this.lastLine.indexOf('.')); - parseTitleString(be, in); + parseTitleString(be, reader); if (startsWithKeyword(RepecNepImporter.RECOGNIZED_FIELDS)) { - parseAdditionalFields(be, false, in); + parseAdditionalFields(be, false, reader); } else { - readLine(in); // skip empty line - parseAuthors(be, in); - readLine(in); // skip empty line + readLine(reader); // skip empty line + parseAuthors(be, reader); + readLine(reader); // skip empty line } if (!startsWithKeyword(RepecNepImporter.RECOGNIZED_FIELDS)) { - parseAbstract(be, in); + parseAbstract(be, reader); } - parseAdditionalFields(be, true, in); + parseAdditionalFields(be, true, reader); bibitems.add(be); paperNoStr = null; } else { this.preLine = this.lastLine; - readLine(in); + readLine(reader); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java index 41c03516efeb..fcdf39314a14 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java @@ -17,14 +17,12 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -56,31 +54,26 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { - + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { // Our strategy is to look for the "AU - *" line. - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - - String str; - while ((str = in.readLine()) != null) { - if (RECOGNIZED_FORMAT_PATTERN.matcher(str).find()) { - return true; - } + String str; + while ((str = reader.readLine()) != null) { + if (RECOGNIZED_FORMAT_PATTERN.matcher(str).find()) { + return true; } } return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { + public ParserResult importDatabase(BufferedReader reader) throws IOException { List bibitems = new ArrayList<>(); StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - String str; - while ((str = in.readLine()) != null) { - sb.append(str); - sb.append('\n'); - } + + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + sb.append('\n'); } String[] entries = sb.toString().replace("\u2013", "-").replace("\u2014", "--").replace("\u2015", "--") @@ -259,14 +252,14 @@ else if ("ID".equals(lab)) { BibEntry b = new BibEntry(DEFAULT_BIBTEXENTRY_ID, type); // id assumes an existing database so don't // Remove empty fields: - List toRemove = new ArrayList<>(); + List toRemove = new ArrayList<>(); for (Map.Entry key : hm.entrySet()) { String content = key.getValue(); if ((content == null) || content.trim().isEmpty()) { toRemove.add(key.getKey()); } } - for (Object aToRemove : toRemove) { + for (String aToRemove : toRemove) { hm.remove(aToRemove); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java index 1cf5cca5f072..fc5e55b33f86 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java @@ -17,13 +17,11 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -52,157 +50,152 @@ public String getDescription() { } @Override - public boolean isRecognizedFormat(InputStream stream) throws IOException { - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - - // This format is very similar to Inspec, so we have a two-fold strategy: - // If we see the flag signaling that it is an Inspec file, return false. - // This flag should appear above the first entry and prevent us from - // accepting the Inspec format. Then we look for the title entry. - String str; - while ((str = in.readLine()) != null) { - - if (START_PATTERN.matcher(str).find()) { - return false; // This is an Inspec file, so return false. - } + public boolean isRecognizedFormat(BufferedReader reader) throws IOException { + // This format is very similar to Inspec, so we have a two-fold strategy: + // If we see the flag signaling that it is an Inspec file, return false. + // This flag should appear above the first entry and prevent us from + // accepting the Inspec format. Then we look for the title entry. + String str; + while ((str = reader.readLine()) != null) { + + if (START_PATTERN.matcher(str).find()) { + return false; // This is an Inspec file, so return false. + } - if ((str.length() >= 5) && "TI: ".equals(str.substring(0, 5))) { - return true; - } + if ((str.length() >= 5) && "TI: ".equals(str.substring(0, 5))) { + return true; } } return false; } @Override - public ParserResult importDatabase(InputStream stream) throws IOException { + public ParserResult importDatabase(BufferedReader reader) throws IOException { List bibitems = new ArrayList<>(); - try (BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream))) { - boolean isChapter = false; - String str; - StringBuilder sb = new StringBuilder(); - while ((str = in.readLine()) != null) { - if (str.length() < 2) { - sb.append("__::__").append(str); - } else { - sb.append("__NEWFIELD__").append(str); - } + boolean isChapter = false; + String str; + StringBuilder sb = new StringBuilder(); + while ((str = reader.readLine()) != null) { + if (str.length() < 2) { + sb.append("__::__").append(str); + } else { + sb.append("__NEWFIELD__").append(str); + } + } + String[] entries = sb.toString().split("__::__"); + String type = ""; + HashMap h = new HashMap<>(); + for (String entry : entries) { + if (entry.trim().length() < 6) { + continue; } - String[] entries = sb.toString().split("__::__"); - String type = ""; - HashMap h = new HashMap<>(); - for (String entry : entries) { - if (entry.trim().length() < 6) { + h.clear(); + String[] fields = entry.split("__NEWFIELD__"); + for (String field : fields) { + if (field.length() < 6) { continue; } - h.clear(); - String[] fields = entry.split("__NEWFIELD__"); - for (String field : fields) { - if (field.length() < 6) { - continue; + String f3 = field.substring(0, 2); + String frest = field.substring(5); + if ("TI".equals(f3)) { + h.put("title", frest); + } else if ("AU".equals(f3)) { + if (frest.trim().endsWith("(ed)")) { + String ed = frest.trim(); + ed = ed.substring(0, ed.length() - 4); + h.put("editor", + AuthorList.fixAuthorLastNameFirst(ed.replace(",-", ", ").replace(";", " and "))); + } else { + h.put("author", + AuthorList.fixAuthorLastNameFirst(frest.replace(",-", ", ").replace(";", " and "))); } - String f3 = field.substring(0, 2); - String frest = field.substring(5); - if ("TI".equals(f3)) { - h.put("title", frest); - } else if ("AU".equals(f3)) { - if (frest.trim().endsWith("(ed)")) { - String ed = frest.trim(); - ed = ed.substring(0, ed.length() - 4); - h.put("editor", - AuthorList.fixAuthorLastNameFirst(ed.replace(",-", ", ").replace(";", " and "))); - } else { - h.put("author", - AuthorList.fixAuthorLastNameFirst(frest.replace(",-", ", ").replace(";", " and "))); - } - } else if ("AB".equals(f3)) { - h.put("abstract", frest); - } else if ("DE".equals(f3)) { - String kw = frest.replace("-;", ",").toLowerCase(); - h.put("keywords", kw.substring(0, kw.length() - 1)); - } else if ("SO".equals(f3)) { - int m = frest.indexOf('.'); - if (m >= 0) { - String jr = frest.substring(0, m); - h.put("journal", jr.replace("-", " ")); + } else if ("AB".equals(f3)) { + h.put("abstract", frest); + } else if ("DE".equals(f3)) { + String kw = frest.replace("-;", ",").toLowerCase(); + h.put("keywords", kw.substring(0, kw.length() - 1)); + } else if ("SO".equals(f3)) { + int m = frest.indexOf('.'); + if (m >= 0) { + String jr = frest.substring(0, m); + h.put("journal", jr.replace("-", " ")); + frest = frest.substring(m); + m = frest.indexOf(';'); + if (m >= 5) { + String yr = frest.substring(m - 5, m).trim(); + h.put("year", yr); frest = frest.substring(m); - m = frest.indexOf(';'); - if (m >= 5) { - String yr = frest.substring(m - 5, m).trim(); - h.put("year", yr); - frest = frest.substring(m); - m = frest.indexOf(':'); - int issueIndex = frest.indexOf('('); - int endIssueIndex = frest.indexOf(')'); - if (m >= 0) { - String pg = frest.substring(m + 1).trim(); - h.put("pages", pg); - h.put("volume", frest.substring(1, issueIndex).trim()); - h.put("issue", frest.substring(issueIndex + 1, endIssueIndex).trim()); - } + m = frest.indexOf(':'); + int issueIndex = frest.indexOf('('); + int endIssueIndex = frest.indexOf(')'); + if (m >= 0) { + String pg = frest.substring(m + 1).trim(); + h.put("pages", pg); + h.put("volume", frest.substring(1, issueIndex).trim()); + h.put("issue", frest.substring(issueIndex + 1, endIssueIndex).trim()); } } - } else if ("PB".equals(f3)) { - int m = frest.indexOf(':'); - if (m >= 0) { - String jr = frest.substring(0, m); - h.put("publisher", jr.replace("-", " ").trim()); - frest = frest.substring(m); - m = frest.indexOf(", "); - if ((m + 2) < frest.length()) { - String yr = frest.substring(m + 2).trim(); - try { - Integer.parseInt(yr); - h.put("year", yr); - } catch (NumberFormatException ex) { - // Let's assume that this wasn't a number, since it - // couldn't be parsed as an integer. - } - + } + } else if ("PB".equals(f3)) { + int m = frest.indexOf(':'); + if (m >= 0) { + String jr = frest.substring(0, m); + h.put("publisher", jr.replace("-", " ").trim()); + frest = frest.substring(m); + m = frest.indexOf(", "); + if ((m + 2) < frest.length()) { + String yr = frest.substring(m + 2).trim(); + try { + Integer.parseInt(yr); + h.put("year", yr); + } catch (NumberFormatException ex) { + // Let's assume that this wasn't a number, since it + // couldn't be parsed as an integer. } } - } else if ("AF".equals(f3)) { - h.put("school", frest.trim()); - - } else if ("DT".equals(f3)) { - frest = frest.trim(); - if ("Monograph".equals(frest)) { - type = "book"; - } else if (frest.startsWith("Dissertation")) { - type = "phdthesis"; - } else if (frest.toLowerCase().contains("journal")) { - type = "article"; - } else if ("Contribution".equals(frest) || "Chapter".equals(frest)) { - type = "incollection"; - // This entry type contains page numbers and booktitle in the - // title field. - isChapter = true; - } else { - type = frest.replace(" ", ""); - } + + } + } else if ("AF".equals(f3)) { + h.put("school", frest.trim()); + + } else if ("DT".equals(f3)) { + frest = frest.trim(); + if ("Monograph".equals(frest)) { + type = "book"; + } else if (frest.startsWith("Dissertation")) { + type = "phdthesis"; + } else if (frest.toLowerCase().contains("journal")) { + type = "article"; + } else if ("Contribution".equals(frest) || "Chapter".equals(frest)) { + type = "incollection"; + // This entry type contains page numbers and booktitle in the + // title field. + isChapter = true; + } else { + type = frest.replace(" ", ""); } } + } - if (isChapter) { - Object titleO = h.get("title"); - if (titleO != null) { - String title = ((String) titleO).trim(); - int inPos = title.indexOf("\" in "); - if (inPos > 1) { - h.put("title", title.substring(0, inPos)); - } + if (isChapter) { + Object titleO = h.get("title"); + if (titleO != null) { + String title = ((String) titleO).trim(); + int inPos = title.indexOf("\" in "); + if (inPos > 1) { + h.put("title", title.substring(0, inPos)); } - } - BibEntry b = new BibEntry(DEFAULT_BIBTEXENTRY_ID, type); // id assumes an existing database so don't - // create one here - b.setField(h); + } - bibitems.add(b); + BibEntry b = new BibEntry(DEFAULT_BIBTEXENTRY_ID, type); // id assumes an existing database so don't + // create one here + b.setField(h); + + bibitems.add(b); - } } return new ParserResult(bibitems); diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java index 46f1c94c5d8c..91bfb3e90a14 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java @@ -15,9 +15,13 @@ */ package net.sf.jabref.logic.msbib; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -32,6 +36,7 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** @@ -57,14 +62,14 @@ public MSBibDatabase(BibDatabase database, List entries) { } } - public List importEntries(InputStream stream) { + public List importEntries(BufferedReader reader) { entries = new HashSet<>(); Document inputDocument; try { DocumentBuilder documentBuilder = DocumentBuilderFactory. newInstance(). newDocumentBuilder(); - inputDocument = documentBuilder.parse(stream); + inputDocument = documentBuilder.parse(new InputSource(reader)); } catch (ParserConfigurationException | SAXException | IOException e) { LOGGER.warn("Could not parse document", e); return Collections.emptyList(); diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index 1b55abf0176d..eadb7bd5fee5 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -124,9 +124,13 @@ public static List readXMP(File file) throws IOException { return result; } - public static PDDocument loadWithAutomaticDecryption(InputStream inputStream) - throws IOException, EncryptedPdfsNotSupportedException { + public static PDDocument loadWithAutomaticDecryption(Path filePath) throws IOException { + return loadWithAutomaticDecryption(new FileInputStream(filePath.toFile())); + } + + public static PDDocument loadWithAutomaticDecryption(InputStream inputStream) throws IOException { PDDocument doc = PDDocument.load(inputStream); + if (doc.isEncrypted()) { // try the empty string as user password StandardDecryptionMaterial sdm = new StandardDecryptionMaterial(""); @@ -209,6 +213,10 @@ public static List readXMP(InputStream inputStream) return result; } + public static Collection readXMP(Path filePath) throws IOException { + return readXMP(filePath.toFile()); + } + /** * Helper function for retrieving a BibEntry from the * PDDocumentInformation in a PDF file. diff --git a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java index ae9f9db4778d..8e9fd8166160 100644 --- a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java +++ b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java @@ -16,9 +16,7 @@ package net.sf.jabref.pdfimport; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -189,15 +187,12 @@ private List importPdfFiles(List fileNames) { private void doXMPImport(String fileName, List res) { List localRes = new ArrayList<>(); PdfXmpImporter importer = new PdfXmpImporter(); - try (InputStream in = new FileInputStream(fileName)) { - ParserResult result = importer.importDatabase(in); - if(result.hasWarnings()) { - frame.showMessage(result.getErrorMessage()); - } - localRes.addAll(result.getDatabase().getEntries()); - } catch (IOException ex) { - LOGGER.warn("Cannot import entries", ex); + Path filePath = Paths.get(fileName); + ParserResult result = importer.importDatabase(filePath, Globals.prefs.getDefaultEncoding()); + if (result.hasWarnings()) { + frame.showMessage(result.getErrorMessage()); } + localRes.addAll(result.getDatabase().getEntries()); BibEntry entry; if (localRes.isEmpty()) { @@ -235,32 +230,24 @@ private BibEntry createNewBlankEntry(String fileName) { } private void doContentImport(String fileName, List res) { - File file = new File(fileName); - BibEntry entry; - try (InputStream in = new FileInputStream(file)) { - PdfContentImporter contentImporter = new PdfContentImporter(); - ParserResult result = contentImporter.importDatabase(in); - if(result.hasWarnings()) { - frame.showMessage(result.getErrorMessage()); - } - if (!result.getDatabase().hasEntries()) { - // import failed -> generate default entry - entry = createNewBlankEntry(fileName); - res.add(entry); - return; - } + PdfContentImporter contentImporter = new PdfContentImporter(); + Path filePath = Paths.get(fileName); + ParserResult result = contentImporter.importDatabase(filePath, Globals.prefs.getDefaultEncoding()); + if (result.hasWarnings()) { + frame.showMessage(result.getErrorMessage()); + } - // only one entry is imported - entry = result.getDatabase().getEntries().get(0); - } catch (IOException e) { + if (!result.getDatabase().hasEntries()) { // import failed -> generate default entry - LOGGER.info("Import failed", e); - entry = createNewBlankEntry(fileName); + BibEntry entry = createNewBlankEntry(fileName); res.add(entry); return; } + // only one entry is imported + BibEntry entry = result.getDatabase().getEntries().get(0); + // insert entry to database and link file panel.getDatabase().insertEntry(entry); panel.markBaseChanged(); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java index b75e139fd189..ac7baf87666e 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java @@ -1,6 +1,8 @@ package net.sf.jabref.importer.fileformat; -import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import net.sf.jabref.Globals; @@ -34,8 +36,8 @@ public void testGetCLIID() { @Test public void testImportEntriesAbortion() throws Throwable { - try (InputStream is = BiblioscapeImporter.class.getResourceAsStream("BiblioscapeImporterTestCorrupt.txt")) { - Assert.assertEquals(Collections.emptyList(), bsImporter.importDatabase(is).getDatabase().getEntries()); - } + Path file = Paths.get(BiblioscapeImporter.class.getResource("BiblioscapeImporterTestCorrupt.txt").toURI()); + Assert.assertEquals(Collections.emptyList(), bsImporter.importDatabase(file, Charset.defaultCharset()) + .getDatabase().getEntries()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java index 6edfccef8588..115bebc42ce0 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java @@ -1,30 +1,38 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.*; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - @RunWith(Parameterized.class) public class BiblioscapeImporterTestFiles { private BiblioscapeImporter bsImporter; - @Parameter - public String fileName; + public Path importFile; + public String bibFile; + public BiblioscapeImporterTestFiles(String fileName) throws URISyntaxException { + importFile = Paths.get(BiblioscapeImporterTest.class.getResource(fileName + ".txt").toURI()); + bibFile = fileName + ".bib"; + } @Before public void setUp() throws Exception { @@ -34,7 +42,7 @@ public void setUp() throws Exception { @Parameters(name = "{0}") public static Collection fileNames() { - return Arrays.asList(new String[] { + return Arrays.asList( "BiblioscapeImporterTestOptionalFields", "BiblioscapeImporterTestComments", "BiblioscapeImporterTestUnknownFields", @@ -42,26 +50,19 @@ public static Collection fileNames() { "BiblioscapeImporterTestJournalArticle", "BiblioscapeImporterTestInbook", "BiblioscapeImporterTestUnknownType", - "BiblioscapeImporterTestArticleST", - }); + "BiblioscapeImporterTestArticleST" + ); } @Test public void testIsRecognizedFormat() throws IOException { - try (InputStream stream = BiblioscapeImporterTest.class.getResourceAsStream(fileName + ".txt")) { - Assert.assertTrue(bsImporter.isRecognizedFormat(stream)); - } + Assert.assertTrue(bsImporter.isRecognizedFormat(importFile, Charset.defaultCharset())); } @Test public void testImportEntries() throws IOException { - try (InputStream bsStream = BiblioscapeImporterTest.class.getResourceAsStream(fileName + ".txt")) { - - List bsEntries = bsImporter.importDatabase(bsStream).getDatabase().getEntries(); - Assert.assertEquals(1, bsEntries.size()); - BibtexEntryAssert.assertEquals(BiblioscapeImporterTest.class, fileName + ".bib", bsEntries); - - - } + List bsEntries = bsImporter.importDatabase(importFile, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(1, bsEntries.size()); + BibtexEntryAssert.assertEquals(BiblioscapeImporterTest.class, bibFile, bsEntries); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java index 16ed3d3a152c..0651cb607cce 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java @@ -1,8 +1,8 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; +import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.StringReader; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -50,8 +50,8 @@ public void importConvertsToCorrectBibType() throws IOException { String bsInput = "--AU-- Baklouti, F.\n" + "--YP-- 1999\n" + "--KW-- Cells; Rna; Isoforms\n" + "--TI-- Blood\n" + "--RT-- " + biblioscapeType + "\n" + "------"; - List bibEntries = bsImporter.importDatabase( - new ByteArrayInputStream(bsInput.getBytes(StandardCharsets.UTF_8))).getDatabase().getEntries(); + List bibEntries = bsImporter.importDatabase(new BufferedReader(new StringReader(bsInput))) + .getDatabase().getEntries(); BibEntry entry = new BibEntry(); entry.setField("author", "Baklouti, F."); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java index 4db2c2963820..ebfe572d9e27 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java @@ -1,7 +1,10 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import net.sf.jabref.Globals; @@ -10,6 +13,7 @@ import org.junit.Before; import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -32,61 +36,59 @@ public void setUp() { } @Test - public void testIsRecognizedFormat() throws IOException { - try (InputStream stream = BibtexImporterTest.class.getResourceAsStream("BibtexImporter.examples.bib")) { - assertTrue(importer.isRecognizedFormat(stream)); - } + public void testIsRecognizedFormat() throws IOException, URISyntaxException { + Path file = Paths.get(BibtexImporterTest.class.getResource("BibtexImporter.examples.bib").toURI()); + assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); } @Test - public void testImportEntries() throws IOException { - try (InputStream stream = BibtexImporterTest.class.getResourceAsStream("BibtexImporter.examples.bib")) { - List bibEntries = importer.importDatabase(stream).getDatabase().getEntries(); + public void testImportEntries() throws IOException, URISyntaxException { + Path file = Paths.get(BibtexImporterTest.class.getResource("BibtexImporter.examples.bib").toURI()); + List bibEntries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); - assertEquals(4, bibEntries.size()); + assertEquals(4, bibEntries.size()); - for (BibEntry entry : bibEntries) { + for (BibEntry entry : bibEntries) { - if (entry.getCiteKey().equals("aksin")) { - assertEquals("Aks{\\i}n, {\\\"O}zge and T{\\\"u}rkmen, Hayati and Artok, Levent and {\\c{C}}etinkaya, " + - "Bekir and Ni, Chaoying and B{\\\"u}y{\\\"u}kg{\\\"u}ng{\\\"o}r, Orhan and {\\\"O}zkal, Erhan", - entry.getField("author")); - assertEquals("aksin", entry.getField("bibtexkey")); - assertEquals("2006", entry.getField("date")); - assertEquals("Effect of immobilization on catalytic characteristics", entry.getField("indextitle")); - assertEquals("#jomch#", entry.getField("journaltitle")); - assertEquals("13", entry.getField("number")); - assertEquals("3027-3036", entry.getField("pages")); - assertEquals("Effect of immobilization on catalytic characteristics of saturated {Pd-N}-heterocyclic " + - "carbenes in {Mizoroki-Heck} reactions", entry.getField("title")); - assertEquals("691", entry.getField("volume")); - } else if (entry.getCiteKey().equals("stdmodel")) { - assertEquals("A \\texttt{set} with three members discussing the standard model of particle physics. " + - "The \\texttt{crossref} field in the \\texttt{@set} entry and the \\texttt{entryset} field in " + - "each set member entry is needed only when using BibTeX as the backend", - entry.getField("annotation")); - assertEquals("stdmodel", entry.getField("bibtexkey")); - assertEquals("glashow,weinberg,salam", entry.getField("entryset")); - } else if (entry.getCiteKey().equals("set")) { - assertEquals("A \\texttt{set} with three members. The \\texttt{crossref} field in the \\texttt{@set} " + - "entry and the \\texttt{entryset} field in each set member entry is needed only when using " + - "BibTeX as the backend", entry.getField("annotation")); - assertEquals("set", entry.getField("bibtexkey")); - assertEquals("herrmann,aksin,yoon", entry.getField("entryset")); - } else if (entry.getCiteKey().equals("Preissel2016")) { - assertEquals("Heidelberg", entry.getField("address")); - assertEquals("Preißel, René", entry.getField("author")); - assertEquals("Preissel2016", entry.getField("bibtexkey")); - assertEquals("3., aktualisierte und erweiterte Auflage", entry.getField("edition")); - assertEquals("978-3-86490-311-3", entry.getField("isbn")); - assertEquals("Versionsverwaltung", entry.getField("keywords")); - assertEquals("XX, 327 Seiten", entry.getField("pages")); - assertEquals("dpunkt.verlag", entry.getField("publisher")); - assertEquals("Git: dezentrale Versionsverwaltung im Team : Grundlagen und Workflows", - entry.getField("title")); - assertEquals("http://d-nb.info/107601965X", entry.getField("url")); - assertEquals("2016", entry.getField("year")); - } + if (entry.getCiteKey().equals("aksin")) { + assertEquals("Aks{\\i}n, {\\\"O}zge and T{\\\"u}rkmen, Hayati and Artok, Levent and {\\c{C}}etinkaya, " + + "Bekir and Ni, Chaoying and B{\\\"u}y{\\\"u}kg{\\\"u}ng{\\\"o}r, Orhan and {\\\"O}zkal, Erhan", + entry.getField("author")); + assertEquals("aksin", entry.getField("bibtexkey")); + assertEquals("2006", entry.getField("date")); + assertEquals("Effect of immobilization on catalytic characteristics", entry.getField("indextitle")); + assertEquals("#jomch#", entry.getField("journaltitle")); + assertEquals("13", entry.getField("number")); + assertEquals("3027-3036", entry.getField("pages")); + assertEquals("Effect of immobilization on catalytic characteristics of saturated {Pd-N}-heterocyclic " + + "carbenes in {Mizoroki-Heck} reactions", entry.getField("title")); + assertEquals("691", entry.getField("volume")); + } else if (entry.getCiteKey().equals("stdmodel")) { + assertEquals("A \\texttt{set} with three members discussing the standard model of particle physics. " + + "The \\texttt{crossref} field in the \\texttt{@set} entry and the \\texttt{entryset} field in " + + "each set member entry is needed only when using BibTeX as the backend", + entry.getField("annotation")); + assertEquals("stdmodel", entry.getField("bibtexkey")); + assertEquals("glashow,weinberg,salam", entry.getField("entryset")); + } else if (entry.getCiteKey().equals("set")) { + assertEquals("A \\texttt{set} with three members. The \\texttt{crossref} field in the \\texttt{@set} " + + "entry and the \\texttt{entryset} field in each set member entry is needed only when using " + + "BibTeX as the backend", entry.getField("annotation")); + assertEquals("set", entry.getField("bibtexkey")); + assertEquals("herrmann,aksin,yoon", entry.getField("entryset")); + } else if (entry.getCiteKey().equals("Preissel2016")) { + assertEquals("Heidelberg", entry.getField("address")); + assertEquals("Preißel, René", entry.getField("author")); + assertEquals("Preissel2016", entry.getField("bibtexkey")); + assertEquals("3., aktualisierte und erweiterte Auflage", entry.getField("edition")); + assertEquals("978-3-86490-311-3", entry.getField("isbn")); + assertEquals("Versionsverwaltung", entry.getField("keywords")); + assertEquals("XX, 327 Seiten", entry.getField("pages")); + assertEquals("dpunkt.verlag", entry.getField("publisher")); + assertEquals("Git: dezentrale Versionsverwaltung im Team : Grundlagen und Workflows", + entry.getField("title")); + assertEquals("http://d-nb.info/107601965X", entry.getField("url")); + assertEquals("2016", entry.getField("year")); } } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java index f293a60eb746..1f4d43983716 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java @@ -1,17 +1,22 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.*; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.List; - public class CopacImporterTest { @Before @@ -22,69 +27,60 @@ public void setUp() throws Exception { } @Test - public void testIsRecognizedFormat() throws IOException { - + public void testIsRecognizedFormat() throws IOException, URISyntaxException { CopacImporter importer = new CopacImporter(); - try (InputStream stream1 = CopacImporterTest.class - .getResourceAsStream("CopacImporterTest1.txt"); InputStream stream2 = CopacImporterTest.class - .getResourceAsStream("CopacImporterTest2.txt"); InputStream stream3 = CopacImporterTest.class - .getResourceAsStream("IsiImporterTest1.isi"); InputStream stream4 = CopacImporterTest.class - .getResourceAsStream("IsiImporterTestInspec.isi"); InputStream stream5 = CopacImporterTest.class - .getResourceAsStream("IsiImporterTestWOS.isi"); InputStream stream6 = CopacImporterTest.class - .getResourceAsStream("IsiImporterTestMedline.isi")) { - - Assert.assertTrue(importer.isRecognizedFormat(stream1)); - - Assert.assertTrue(importer.isRecognizedFormat(stream2)); - - Assert.assertFalse(importer.isRecognizedFormat(stream3)); - - Assert.assertFalse(importer.isRecognizedFormat(stream4)); - - Assert.assertFalse(importer.isRecognizedFormat(stream5)); + List list = Arrays.asList("CopacImporterTest1.txt", "CopacImporterTest2.txt"); + for (String str : list) { + Path file = Paths.get(CopacImporterTest.class.getResource(str).toURI()); + Assert.assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); + } + } - Assert.assertFalse(importer.isRecognizedFormat(stream6)); + @Test + public void testIsNotRecognizedFormat() throws IOException, URISyntaxException { + CopacImporter importer = new CopacImporter(); + List list = Arrays.asList("IsiImporterTest1.isi", "IsiImporterTestInspec.isi", "IsiImporterTestWOS.isi", + "IsiImporterTestMedline.isi"); + for (String str : list) { + Path file = Paths.get(CopacImporterTest.class.getResource(str).toURI()); + Assert.assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testImportEntries() throws IOException { + public void testImportEntries() throws IOException, URISyntaxException { Globals.prefs.put("defaultEncoding", StandardCharsets.UTF_8.name()); CopacImporter importer = new CopacImporter(); - try (InputStream stream = CopacImporterTest.class - .getResourceAsStream("CopacImporterTest1.txt")) { - List entries = importer.importDatabase(stream).getDatabase().getEntries(); - Assert.assertEquals(1, entries.size()); - BibEntry entry = entries.get(0); + Path file = Paths.get(CopacImporterTest.class.getResource("CopacImporterTest1.txt").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(1, entries.size()); + BibEntry entry = entries.get(0); - Assert.assertEquals("The SIS project : software reuse with a natural language approach", entry.getField("title")); - Assert.assertEquals( + Assert.assertEquals("The SIS project : software reuse with a natural language approach", entry.getField("title")); + Assert.assertEquals( "Prechelt, Lutz and Universität Karlsruhe. Fakultät für Informatik", - entry.getField("author")); - Assert.assertEquals("Interner Bericht ; Nr.2/92", entry.getField("series")); - Assert.assertEquals("1992", entry.getField("year")); - Assert.assertEquals("Karlsruhe : Universitat Karlsruhe, Fakultat fur Informatik", entry.getField("publisher")); - Assert.assertEquals("book", entry.getType()); - } + entry.getField("author")); + Assert.assertEquals("Interner Bericht ; Nr.2/92", entry.getField("series")); + Assert.assertEquals("1992", entry.getField("year")); + Assert.assertEquals("Karlsruhe : Universitat Karlsruhe, Fakultat fur Informatik", entry.getField("publisher")); + Assert.assertEquals("book", entry.getType()); } @Test - public void testImportEntries2() throws IOException { + public void testImportEntries2() throws IOException, URISyntaxException { CopacImporter importer = new CopacImporter(); - try (InputStream stream = CopacImporterTest.class - .getResourceAsStream("CopacImporterTest2.txt")) { - List entries = importer.importDatabase(stream).getDatabase().getEntries(); - Assert.assertEquals(2, entries.size()); - BibEntry one = entries.get(0); + Path file = Paths.get(CopacImporterTest.class.getResource("CopacImporterTest2.txt").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(2, entries.size()); + BibEntry one = entries.get(0); - Assert.assertEquals("Computing and operational research at the London Hospital", one.getField("title")); + Assert.assertEquals("Computing and operational research at the London Hospital", one.getField("title")); - BibEntry two = entries.get(1); + BibEntry two = entries.get(1); - Assert.assertEquals("Real time systems : management and design", two.getField("title")); - } + Assert.assertEquals("Real time systems : management and design", two.getField("title")); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index f059ae19686c..da2bd3b85058 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -1,19 +1,25 @@ package net.sf.jabref.importer.fileformat; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; + import org.junit.Before; import org.junit.Test; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class EndnoteImporterTest { @@ -37,80 +43,76 @@ public void testGetCLIId() { } @Test - public void testIsRecognizedFormat() throws IOException { + public void testIsRecognizedFormat() throws IOException, URISyntaxException { List list = Arrays.asList("Endnote.pattern.A.enw", "Endnote.pattern.E.enw", "Endnote.book.example.enw"); for (String str : list) { - try (InputStream is = EndnoteImporterTest.class.getResourceAsStream(str)) { - assertTrue(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(EndnoteImporterTest.class.getResource(str).toURI()); + assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testIsRecognizedFormatReject() throws IOException { + public void testIsRecognizedFormatReject() throws IOException, URISyntaxException { List list = Arrays.asList("IEEEImport1.txt", "IsiImporterTest1.isi", "IsiImporterTestInspec.isi", "IsiImporterTestWOS.isi", "IsiImporterTestMedline.isi", "RisImporterTest1.ris", "Endnote.pattern.no_enw", "empty.pdf", "annotated.pdf"); for (String str : list) { - try (InputStream is = EndnoteImporterTest.class.getResourceAsStream(str)) { - assertFalse(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(EndnoteImporterTest.class.getResource(str).toURI()); + assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testImportEntries0() throws IOException { - try (InputStream is = EndnoteImporterTest.class.getResourceAsStream("Endnote.entries.enw")) { - List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); - - assertEquals(5, bibEntries.size()); - - BibEntry be0 = bibEntries.get(0); - assertEquals("misc", be0.getType()); - assertEquals("testA0 and testA1", be0.getField("author")); - assertEquals("testE0 and testE1", be0.getField("editor")); - assertEquals("testT", be0.getField("title")); - - BibEntry be1 = bibEntries.get(1); - assertEquals("misc", be1.getType()); - assertEquals("testC", be1.getField("address")); - assertEquals("testB2", be1.getField("booktitle")); - assertEquals("test8", be1.getField("date")); - assertEquals("test7", be1.getField("edition")); - assertEquals("testJ", be1.getField("journal")); - assertEquals("testD", be1.getField("year")); - - BibEntry be2 = bibEntries.get(2); - assertEquals("article", be2.getType()); - assertEquals("testB0", be2.getField("journal")); - - BibEntry be3 = bibEntries.get(3); - assertEquals("book", be3.getType()); - assertEquals("testI0", be3.getField("publisher")); - assertEquals("testB1", be3.getField("series")); - - BibEntry be4 = bibEntries.get(4); - assertEquals("mastersthesis", be4.getType()); - assertEquals("testX", be4.getField("abstract")); - assertEquals("testF", be4.getField("bibtexkey")); - assertEquals("testR", be4.getField("doi")); - assertEquals("testK", be4.getField("keywords")); - assertEquals("testO1", be4.getField("note")); - assertEquals("testN", be4.getField("number")); - assertEquals("testP", be4.getField("pages")); - assertEquals("testI1", be4.getField("school")); - assertEquals("testU", be4.getField("url")); - assertEquals("testV", be4.getField("volume")); - } + public void testImportEntries0() throws IOException, URISyntaxException { + Path file = Paths.get(EndnoteImporterTest.class.getResource("Endnote.entries.enw").toURI()); + List bibEntries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + + assertEquals(5, bibEntries.size()); + + BibEntry be0 = bibEntries.get(0); + assertEquals("misc", be0.getType()); + assertEquals("testA0 and testA1", be0.getField("author")); + assertEquals("testE0 and testE1", be0.getField("editor")); + assertEquals("testT", be0.getField("title")); + + BibEntry be1 = bibEntries.get(1); + assertEquals("misc", be1.getType()); + assertEquals("testC", be1.getField("address")); + assertEquals("testB2", be1.getField("booktitle")); + assertEquals("test8", be1.getField("date")); + assertEquals("test7", be1.getField("edition")); + assertEquals("testJ", be1.getField("journal")); + assertEquals("testD", be1.getField("year")); + + BibEntry be2 = bibEntries.get(2); + assertEquals("article", be2.getType()); + assertEquals("testB0", be2.getField("journal")); + + BibEntry be3 = bibEntries.get(3); + assertEquals("book", be3.getType()); + assertEquals("testI0", be3.getField("publisher")); + assertEquals("testB1", be3.getField("series")); + + BibEntry be4 = bibEntries.get(4); + assertEquals("mastersthesis", be4.getType()); + assertEquals("testX", be4.getField("abstract")); + assertEquals("testF", be4.getField("bibtexkey")); + assertEquals("testR", be4.getField("doi")); + assertEquals("testK", be4.getField("keywords")); + assertEquals("testO1", be4.getField("note")); + assertEquals("testN", be4.getField("number")); + assertEquals("testP", be4.getField("pages")); + assertEquals("testI1", be4.getField("school")); + assertEquals("testU", be4.getField("url")); + assertEquals("testV", be4.getField("volume")); } @Test public void testImportEntries1() throws IOException { String s = "%O Artn\\\\s testO\n%A testA,\n%E testE0, testE1"; - InputStream is = new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)); - List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(new BufferedReader(new StringReader(s))).getDatabase().getEntries(); assertEquals(1, bibEntries.size()); @@ -122,23 +124,22 @@ public void testImportEntries1() throws IOException { } @Test - public void testImportEntriesBookExample() throws IOException { - try (InputStream is = EndnoteImporterTest.class.getResourceAsStream("Endnote.book.example.enw")) { - List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); - - assertEquals(1, bibEntries.size()); - - BibEntry be = bibEntries.get(0); - assertEquals("book", be.getType()); - assertEquals("Heidelberg", be.getField("address")); - assertEquals("Preißel, René and Stachmann, Bjørn", be.getField("author")); - assertEquals("3., aktualisierte und erweiterte Auflage", be.getField("edition")); - assertEquals("Versionsverwaltung", be.getField("keywords")); - assertEquals("XX, 327", be.getField("pages")); - assertEquals("dpunkt.verlag", be.getField("publisher")); - assertEquals("Git : dezentrale Versionsverwaltung im Team : Grundlagen und Workflows", be.getField("title")); - assertEquals("http://d-nb.info/107601965X", be.getField("url")); - assertEquals("2016", be.getField("year")); - } + public void testImportEntriesBookExample() throws IOException, URISyntaxException { + Path file = Paths.get(EndnoteImporterTest.class.getResource("Endnote.book.example.enw").toURI()); + List bibEntries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + + assertEquals(1, bibEntries.size()); + + BibEntry be = bibEntries.get(0); + assertEquals("book", be.getType()); + assertEquals("Heidelberg", be.getField("address")); + assertEquals("Preißel, René and Stachmann, Bjørn", be.getField("author")); + assertEquals("3., aktualisierte und erweiterte Auflage", be.getField("edition")); + assertEquals("Versionsverwaltung", be.getField("keywords")); + assertEquals("XX, 327", be.getField("pages")); + assertEquals("dpunkt.verlag", be.getField("publisher")); + assertEquals("Git : dezentrale Versionsverwaltung im Team : Grundlagen und Workflows", be.getField("title")); + assertEquals("http://d-nb.info/107601965X", be.getField("url")); + assertEquals("2016", be.getField("year")); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java index 2265ebf5b489..8e148d54166f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java @@ -1,9 +1,6 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.regex.Pattern; @@ -16,6 +13,7 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.mockito.Mockito; + import static org.mockito.Mockito.when; @RunWith(Parameterized.class) @@ -26,18 +24,12 @@ public class ImportFormatTest { @Test(expected = NullPointerException.class) public void isRecognizedFormatWithNullThrowsException() throws IOException { - format.isRecognizedFormat((InputStream)null); + format.isRecognizedFormat(null); } @Test(expected = NullPointerException.class) public void importDatabaseWithNullThrowsException() throws IOException { - format.importDatabase((InputStream)null); - } - - @Test - public void importDatabaseWithUnrecognizedInputDoesNotReturnNull() throws IOException { - InputStream stream = new ByteArrayInputStream("!#!bad string".getBytes(StandardCharsets.UTF_8)); - Assert.assertNotNull(format.importDatabase(stream)); + format.importDatabase(null); } @Test @@ -102,4 +94,4 @@ public static Collection instancesToTest() { ); // @formatter:on } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index 309a18b1fef2..647e412c1bc9 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -1,8 +1,12 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; +import java.io.StringReader; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; @@ -13,6 +17,7 @@ import org.junit.Before; import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -28,29 +33,27 @@ public void setUp() throws Exception { } @Test - public void testIsRecognizedFormatAccept() throws IOException { + public void testIsRecognizedFormatAccept() throws IOException, URISyntaxException { List testList = Arrays.asList("InspecImportTest.txt", "InspecImportTest2.txt"); for (String str : testList) { - try (InputStream inStream = InspecImportTest.class.getResourceAsStream(str)) { - assertTrue(inspecImp.isRecognizedFormat(inStream)); - } + Path file = Paths.get(InspecImportTest.class.getResource(str).toURI()); + assertTrue(inspecImp.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testIsRecognizedFormatReject() throws IOException { + public void testIsRecognizedFormatReject() throws IOException, URISyntaxException { List testList = Arrays.asList("CopacImporterTest1.txt", "CopacImporterTest2.txt", "IEEEImport1.txt", "IsiImporterTest1.isi", "IsiImporterTestInspec.isi", "IsiImporterTestWOS.isi", "IsiImporterTestMedline.isi", "RisImporterTest1.ris", "InspecImportTestFalse.txt"); for (String str : testList) { - try (InputStream inStream = InspecImportTest.class.getResourceAsStream(str)) { - assertFalse(inspecImp.isRecognizedFormat(inStream)); - } + Path file = Paths.get(InspecImportTest.class.getResource(str).toURI()); + assertFalse(inspecImp.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testCompleteBibtexEntryOnJournalPaperImport() throws IOException { + public void testCompleteBibtexEntryOnJournalPaperImport() throws IOException, URISyntaxException { BibEntry shouldBeEntry = new BibEntry(); shouldBeEntry.setType("article"); @@ -63,13 +66,11 @@ public void testCompleteBibtexEntryOnJournalPaperImport() throws IOException { shouldBeEntry.setField("pages", "20"); shouldBeEntry.setField("volume", "19"); - try (InputStream inStream = InspecImportTest.class.getResourceAsStream("InspecImportTest2.txt")) { - List entries = inspecImp.importDatabase(inStream).getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.get(0); - BibtexEntryAssert.assertEquals(shouldBeEntry, entry); - - } + Path file = Paths.get(InspecImportTest.class.getResource("InspecImportTest2.txt").toURI()); + List entries = inspecImp.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + assertEquals(1, entries.size()); + BibEntry entry = entries.get(0); + BibtexEntryAssert.assertEquals(shouldBeEntry, entry); } @Test @@ -82,8 +83,8 @@ public void importConferencePaperGivesInproceedings() throws IOException { shouldBeEntry.setType("Inproceedings"); shouldBeEntry.setField("author", "Prechelt, Lutz"); - try (InputStream inStream = new ByteArrayInputStream(testInput.getBytes())) { - List entries = inspecImp.importDatabase(inStream).getDatabase().getEntries(); + try (BufferedReader reader = new BufferedReader(new StringReader(testInput))) { + List entries = inspecImp.importDatabase(reader).getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.get(0); BibtexEntryAssert.assertEquals(shouldBeEntry, entry); @@ -100,8 +101,8 @@ public void importMiscGivesMisc() throws IOException { shouldBeEntry.setType("Misc"); shouldBeEntry.setField("author", "Prechelt, Lutz"); - try (InputStream inStream = new ByteArrayInputStream(testInput.getBytes())) { - List entries = inspecImp.importDatabase(inStream).getDatabase().getEntries(); + try (BufferedReader reader = new BufferedReader(new StringReader(testInput))) { + List entries = inspecImp.importDatabase(reader).getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.get(0); BibtexEntryAssert.assertEquals(shouldBeEntry, entry); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java index 7218f6d9f640..6d7fe7fd59fd 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java @@ -1,7 +1,10 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -50,7 +53,7 @@ public void testGetCLIId() { } @Test - public void testIsRecognizedFormatAccepted() throws IOException { + public void testIsRecognizedFormatAccepted() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); @@ -58,23 +61,21 @@ public void testIsRecognizedFormatAccepted() throws IOException { "IsiImporterTestWOS.isi", "IsiImporterTestMedline.isi"); for (String str : list) { - try (InputStream is = IsiImporterTest.class.getResourceAsStream(str)) { - Assert.assertTrue(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(IsiImporterTest.class.getResource(str).toURI()); + Assert.assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testIsRecognizedFormatRejected() throws IOException { + public void testIsRecognizedFormatRejected() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); List list = Arrays.asList("IsiImporterTestEmpty.isi"); for (String str : list) { - try (InputStream is = IsiImporterTest.class.getResourceAsStream(str)) { - Assert.assertFalse(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(IsiImporterTest.class.getResource(str).toURI()); + Assert.assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @@ -124,109 +125,97 @@ public void testProcessSubSup() { } @Test - public void testImportEntries1() throws IOException { + public void testImportEntries1() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); - - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTest1.isi")) { - - List entries = importer.importDatabase(is).getDatabase().getEntries(); - Assert.assertEquals(1, entries.size()); - BibEntry entry = entries.get(0); - Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); - Assert.assertEquals( - "James Brown and James Marc Brown and Brown, J. M. and Brown, J. and Brown, J. M. and Brown, J.", - entry.getField("author")); - - Assert.assertEquals("article", entry.getType()); - Assert.assertEquals("Optical Materials", entry.getField("journal")); - Assert.assertEquals("2006", entry.getField("year")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("5", entry.getField("number")); - Assert.assertEquals("467--72", entry.getField("pages")); - } + Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTest1.isi").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(1, entries.size()); + BibEntry entry = entries.get(0); + Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); + Assert.assertEquals( + "James Brown and James Marc Brown and Brown, J. M. and Brown, J. and Brown, J. M. and Brown, J.", + entry.getField("author")); + + Assert.assertEquals("article", entry.getType()); + Assert.assertEquals("Optical Materials", entry.getField("journal")); + Assert.assertEquals("2006", entry.getField("year")); + Assert.assertEquals("28", entry.getField("volume")); + Assert.assertEquals("5", entry.getField("number")); + Assert.assertEquals("467--72", entry.getField("pages")); } @Test - public void testImportEntries2() throws IOException { + public void testImportEntries2() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); - - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTest2.isi")) { - - List entries = importer.importDatabase(is).getDatabase().getEntries(); - Assert.assertEquals(3, entries.size()); - BibEntry entry = entries.get(0); - Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); - - Assert.assertEquals("misc", entry.getType()); - Assert.assertEquals("Optical Materials", entry.getField("journal")); - Assert.assertEquals("2006", entry.getField("year")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("5", entry.getField("number")); - Assert.assertEquals("467-72", entry.getField("pages")); - } + Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTest2.isi").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(3, entries.size()); + BibEntry entry = entries.get(0); + Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); + + Assert.assertEquals("misc", entry.getType()); + Assert.assertEquals("Optical Materials", entry.getField("journal")); + Assert.assertEquals("2006", entry.getField("year")); + Assert.assertEquals("28", entry.getField("volume")); + Assert.assertEquals("5", entry.getField("number")); + Assert.assertEquals("467-72", entry.getField("pages")); } @Test - public void testImportEntriesINSPEC() throws IOException { + public void testImportEntriesINSPEC() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); - - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestInspec.isi")) { - - List entries = importer.importDatabase(is).getDatabase().getEntries(); - - Assert.assertEquals(2, entries.size()); - BibEntry a = entries.get(0); - BibEntry b = entries.get(1); - - if (a.getField("title") - .equals("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals")) { - BibEntry tmp = a; - a = b; - b = tmp; - } - - Assert.assertEquals( - "Second harmonic generation of continuous wave ultraviolet light and production of beta -BaB$_2$O$_4$ optical waveguides", - a.getField("title")); - Assert.assertEquals("article", a.getType()); - - Assert.assertEquals("Degl'Innocenti, R. and Guarino, A. and Poberaj, G. and Gunter, P.", - a.getField("author")); - Assert.assertEquals("Applied Physics Letters", a.getField("journal")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals("#jul#", a.getField("month")); - Assert.assertEquals("89", a.getField("volume")); - Assert.assertEquals("4", a.getField("number")); - Assert.assertEquals( - "Lorem ipsum abstract", - a.getField("abstract")); - Assert.assertEquals("Aip", a.getField("publisher")); - - Assert.assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals", - b.getField("title")); - Assert.assertEquals("article", b.getType()); + Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestInspec.isi").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + + Assert.assertEquals(2, entries.size()); + BibEntry a = entries.get(0); + BibEntry b = entries.get(1); + + if (a.getField("title") + .equals("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals")) { + BibEntry tmp = a; + a = b; + b = tmp; } + + Assert.assertEquals( + "Second harmonic generation of continuous wave ultraviolet light and production of beta -BaB$_2$O$_4$ optical waveguides", + a.getField("title")); + Assert.assertEquals("article", a.getType()); + + Assert.assertEquals("Degl'Innocenti, R. and Guarino, A. and Poberaj, G. and Gunter, P.", + a.getField("author")); + Assert.assertEquals("Applied Physics Letters", a.getField("journal")); + Assert.assertEquals("2006", a.getField("year")); + Assert.assertEquals("#jul#", a.getField("month")); + Assert.assertEquals("89", a.getField("volume")); + Assert.assertEquals("4", a.getField("number")); + Assert.assertEquals( + "Lorem ipsum abstract", + a.getField("abstract")); + Assert.assertEquals("Aip", a.getField("publisher")); + + Assert.assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals", + b.getField("title")); + Assert.assertEquals("article", b.getType()); } @Test - public void testImportEntriesWOS() throws IOException { + public void testImportEntriesWOS() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); + Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestWOS.isi").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestWOS.isi")) { + Assert.assertEquals(2, entries.size()); + BibEntry a = entries.get(0); + BibEntry b = entries.get(1); - List entries = importer.importDatabase(is).getDatabase().getEntries(); + Assert.assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn2P2S6 crystals", + a.getField("title")); + Assert.assertEquals("Optical waveguides in Sn2P2S6 by low fluence MeV He+ ion implantation", + b.getField("title")); - Assert.assertEquals(2, entries.size()); - BibEntry a = entries.get(0); - BibEntry b = entries.get(1); - - Assert.assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn2P2S6 crystals", - a.getField("title")); - Assert.assertEquals("Optical waveguides in Sn2P2S6 by low fluence MeV He+ ion implantation", - b.getField("title")); - - Assert.assertEquals("Journal of Physics-condensed Matter", a.getField("journal")); - } + Assert.assertEquals("Journal of Physics-condensed Matter", a.getField("journal")); } @Test @@ -270,109 +259,96 @@ public void testIsiAuthorConvert() { } @Test - public void testImportIEEEExport() throws IOException { + public void testImportIEEEExport() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); + Path file = Paths.get(IsiImporterTest.class.getResource("IEEEImport1.txt").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + + Assert.assertEquals(1, entries.size()); + BibEntry a = entries.get(0); + Assert.assertEquals("article", a.getType()); + Assert.assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal")); + Assert.assertEquals("Improving Urban Road Extraction in High-Resolution " + + "Images Exploiting Directional Filtering, Perceptual " + + "Grouping, and Simple Topological Concepts", a.getField("title")); + Assert.assertEquals("4", a.getField("volume")); + Assert.assertEquals("3", a.getField("number")); + Assert.assertEquals("1545-598X", a.getField("SN")); + Assert.assertEquals("387--391", a.getField("pages")); + Assert.assertEquals("Gamba, P. and Dell'Acqua, F. and Lisini, G.", a.getField("author")); + Assert.assertEquals("2006", a.getField("year")); + Assert.assertEquals("Perceptual grouping, street extraction, urban remote sensing", a.getField("keywords")); + Assert.assertEquals("Lorem ipsum abstract", a.getField("abstract")); + } - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IEEEImport1.txt")) { - - List entries = importer.importDatabase(is).getDatabase().getEntries(); - - Assert.assertEquals(1, entries.size()); - BibEntry a = entries.get(0); - Assert.assertEquals("article", a.getType()); - Assert.assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal")); - Assert.assertEquals("Improving Urban Road Extraction in High-Resolution " - + "Images Exploiting Directional Filtering, Perceptual " - + "Grouping, and Simple Topological Concepts", a.getField("title")); - Assert.assertEquals("4", a.getField("volume")); - Assert.assertEquals("3", a.getField("number")); - Assert.assertEquals("1545-598X", a.getField("SN")); - Assert.assertEquals("387--391", a.getField("pages")); - Assert.assertEquals("Gamba, P. and Dell'Acqua, F. and Lisini, G.", a.getField("author")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals("Perceptual grouping, street extraction, urban remote sensing", a.getField("keywords")); - Assert.assertEquals("Lorem ipsum abstract", - a.getField("abstract")); + @Test + public void testIEEEImport() throws IOException, URISyntaxException { + IsiImporter importer = new IsiImporter(); + Path file = Paths.get(IsiImporterTest.class.getResource("IEEEImport1.txt").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); - } + Assert.assertEquals(1, entries.size()); + BibEntry a = entries.get(0); + + Assert.assertEquals("article", a.getType()); + Assert.assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal")); + Assert.assertEquals( + "Improving Urban Road Extraction in High-Resolution Images Exploiting Directional Filtering, Perceptual Grouping, and Simple Topological Concepts", + a.getField("title")); + Assert.assertEquals("4", a.getField("volume")); + Assert.assertEquals("3", a.getField("number")); + Assert.assertEquals("1545-598X", a.getField("SN")); + Assert.assertEquals("387--391", a.getField("pages")); + Assert.assertEquals("Gamba, P. and Dell'Acqua, F. and Lisini, G.", a.getField("author")); + Assert.assertEquals("2006", a.getField("year")); + Assert.assertEquals("Perceptual grouping, street extraction, urban remote sensing", a.getField("keywords")); + Assert.assertEquals("Lorem ipsum abstract", a.getField("abstract")); } @Test - public void testIEEEImport() throws IOException { + public void testImportEntriesMedline() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); + Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestMedline.isi").toURI()); - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IEEEImport1.txt")) { - - List entries = importer.importDatabase(is).getDatabase().getEntries(); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); - Assert.assertEquals(1, entries.size()); - BibEntry a = entries.get(0); + Assert.assertEquals(2, entries.size()); + BibEntry a = entries.get(0); + BibEntry b = entries.get(1); - Assert.assertEquals("article", a.getType()); - Assert.assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal")); - Assert.assertEquals( - "Improving Urban Road Extraction in High-Resolution Images Exploiting Directional Filtering, Perceptual Grouping, and Simple Topological Concepts", - a.getField("title")); - Assert.assertEquals("4", a.getField("volume")); - Assert.assertEquals("3", a.getField("number")); - Assert.assertEquals("1545-598X", a.getField("SN")); - Assert.assertEquals("387--391", a.getField("pages")); - Assert.assertEquals("Gamba, P. and Dell'Acqua, F. and Lisini, G.", a.getField("author")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals("Perceptual grouping, street extraction, urban remote sensing", a.getField("keywords")); - Assert.assertEquals("Lorem ipsum abstract", - a.getField("abstract")); + Assert.assertEquals("Effects of modafinil on cognitive performance and alertness during sleep deprivation.", + a.getField("title")); - } - } + Assert.assertEquals("Wesensten, Nancy J.", a.getField("author")); + Assert.assertEquals("Curr Pharm Des", a.getField("journal")); + Assert.assertEquals("2006", a.getField("year")); + Assert.assertEquals(null, a.getField("month")); + Assert.assertEquals("12", a.getField("volume")); + Assert.assertEquals("20", a.getField("number")); + Assert.assertEquals("2457--71", a.getField("pages")); + Assert.assertEquals("article", a.getType()); - @Test - public void testImportEntriesMedline() throws IOException { - IsiImporter importer = new IsiImporter(); - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestMedline.isi")) { - - List entries = importer.importDatabase(is).getDatabase().getEntries(); - - Assert.assertEquals(2, entries.size()); - BibEntry a = entries.get(0); - BibEntry b = entries.get(1); - - Assert.assertEquals("Effects of modafinil on cognitive performance and alertness during sleep deprivation.", - a.getField("title")); - - Assert.assertEquals("Wesensten, Nancy J.", a.getField("author")); - Assert.assertEquals("Curr Pharm Des", a.getField("journal")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals(null, a.getField("month")); - Assert.assertEquals("12", a.getField("volume")); - Assert.assertEquals("20", a.getField("number")); - Assert.assertEquals("2457--71", a.getField("pages")); - Assert.assertEquals("article", a.getType()); - - Assert.assertEquals( - "Estrogen therapy selectively enhances prefrontal cognitive processes: a randomized, double-blind, placebo-controlled study with functional magnetic resonance imaging in perimenopausal and recently postmenopausal women.", - b.getField("title")); - Assert.assertEquals( - "Joffe, Hadine and Hall, Janet E. and Gruber, Staci and Sarmiento, Ingrid A. and Cohen, Lee S. and Yurgelun-Todd, Deborah and Martin, Kathryn A.", - b.getField("author")); - Assert.assertEquals("2006", b.getField("year")); - Assert.assertEquals("#may#", b.getField("month")); - Assert.assertEquals("13", b.getField("volume")); - Assert.assertEquals("3", b.getField("number")); - Assert.assertEquals("411--22", b.getField("pages")); - Assert.assertEquals("article", b.getType()); - } + Assert.assertEquals( + "Estrogen therapy selectively enhances prefrontal cognitive processes: a randomized, double-blind, placebo-controlled study with functional magnetic resonance imaging in perimenopausal and recently postmenopausal women.", + b.getField("title")); + Assert.assertEquals( + "Joffe, Hadine and Hall, Janet E. and Gruber, Staci and Sarmiento, Ingrid A. and Cohen, Lee S. and Yurgelun-Todd, Deborah and Martin, Kathryn A.", + b.getField("author")); + Assert.assertEquals("2006", b.getField("year")); + Assert.assertEquals("#may#", b.getField("month")); + Assert.assertEquals("13", b.getField("volume")); + Assert.assertEquals("3", b.getField("number")); + Assert.assertEquals("411--22", b.getField("pages")); + Assert.assertEquals("article", b.getType()); } @Test - public void testImportEntriesEmpty() throws IOException { + public void testImportEntriesEmpty() throws IOException, URISyntaxException { IsiImporter importer = new IsiImporter(); + Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestEmpty.isi").toURI()); - try (InputStream is = IsiImporterTest.class.getResourceAsStream("IsiImporterTestEmpty.isi")) { + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); - List entries = importer.importDatabase(is).getDatabase().getEntries(); - - Assert.assertEquals(1, entries.size()); - } + Assert.assertEquals(1, entries.size()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index 9510b0b9760e..7db16d89d0d8 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -1,9 +1,13 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.io.StringReader; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -19,12 +23,10 @@ public class MedlinePlainImporterTest { - private final InputStream emptyFileStream = streamForString(""); private MedlinePlainImporter importer; - - private InputStream streamForString(String string) { - return new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8)); + private BufferedReader readerForString(String string) { + return new BufferedReader(new StringReader(string)); } @Before @@ -34,13 +36,12 @@ public void setUp() { } @Test - public void testIsRecognizedFormat() throws IOException { + public void testIsRecognizedFormat() throws IOException, URISyntaxException { List list = Arrays.asList("CopacImporterTest1.txt", "CopacImporterTest2.txt", "IsiImporterTest1.isi", "IsiImporterTestInspec.isi", "IsiImporterTestWOS.isi", "IsiImporterTestMedline.isi"); for (String str : list) { - try (InputStream is = MedlinePlainImporter.class.getResourceAsStream(str)) { - Assert.assertFalse(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(MedlinePlainImporter.class.getResource(str).toURI()); + Assert.assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @@ -51,73 +52,72 @@ public void testIsNotRecognizedFormat() throws Exception { "MedlinePlainImporterTestMultiTitle.txt", "MedlinePlainImporterTestDOI.txt", "MedlinePlainImporterTestInproceeding.txt"); for (String str : list) { - try (InputStream is = MedlinePlainImporter.class.getResourceAsStream(str)) { - Assert.assertTrue(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(MedlinePlainImporter.class.getResource(str).toURI()); + Assert.assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testIsNotEmptyFileRecognizedFormat() throws IOException { - Assert.assertFalse(importer.isRecognizedFormat(emptyFileStream)); + public void doesNotRecognizeEmptyFiles() throws IOException { + Assert.assertFalse(importer.isRecognizedFormat(readerForString(""))); } @Test - public void testImportMultipleEntriesInSingleFile() throws IOException { - try (InputStream is = MedlinePlainImporter.class - .getResourceAsStream("MedlinePlainImporterTestMultipleEntries.txt")) { - - List entries = importer.importDatabase(is).getDatabase().getEntries(); - Assert.assertEquals(7, entries.size()); - - BibEntry testEntry = entries.get(0); - Assert.assertEquals("article", testEntry.getType()); - Assert.assertNull(testEntry.getField("month")); - Assert.assertEquals("Long, Vicky and Marland, Hilary", testEntry.getField("author")); - Assert.assertEquals( - "From danger and motherhood to health and beauty: health advice for the factory girl in early twentieth-century Britain.", - testEntry.getField("title")); - - testEntry = entries.get(1); - Assert.assertEquals("conference", testEntry.getType()); - Assert.assertEquals("06", testEntry.getField("month")); - Assert.assertNull(testEntry.getField("author")); - Assert.assertNull(testEntry.getField("title")); - - testEntry = entries.get(2); - Assert.assertEquals("book", testEntry.getType()); - Assert.assertEquals( - "This is a Testtitle: This title should be appended: This title should also be appended. Another append to the Title? LastTitle", - testEntry.getField("title")); - - testEntry = entries.get(3); - Assert.assertEquals("techreport", testEntry.getType()); - Assert.assertNotNull(testEntry.getField("doi")); - - testEntry = entries.get(4); - Assert.assertEquals("inproceedings", testEntry.getType()); - Assert.assertEquals("Inproceedings book title", testEntry.getField("booktitle")); - - BibEntry expectedEntry5 = new BibEntry(); - expectedEntry5.setType("proceedings"); - expectedEntry5.setField("keywords", "Female"); - BibtexEntryAssert.assertEquals(expectedEntry5, entries.get(5)); - - BibEntry expectedEntry6 = new BibEntry(); - expectedEntry6.setType("misc"); - expectedEntry6.setField("keywords", "Female"); - BibtexEntryAssert.assertEquals(expectedEntry6, entries.get(6)); - } + public void testImportMultipleEntriesInSingleFile() throws IOException, URISyntaxException { + Path inputFile = Paths.get( + MedlinePlainImporter.class.getResource("MedlinePlainImporterTestMultipleEntries.txt").toURI()); + + List entries = importer.importDatabase(inputFile, Charset.defaultCharset()).getDatabase() + .getEntries(); + Assert.assertEquals(7, entries.size()); + + BibEntry testEntry = entries.get(0); + Assert.assertEquals("article", testEntry.getType()); + Assert.assertNull(testEntry.getField("month")); + Assert.assertEquals("Long, Vicky and Marland, Hilary", testEntry.getField("author")); + Assert.assertEquals( + "From danger and motherhood to health and beauty: health advice for the factory girl in early twentieth-century Britain.", + testEntry.getField("title")); + + testEntry = entries.get(1); + Assert.assertEquals("conference", testEntry.getType()); + Assert.assertEquals("06", testEntry.getField("month")); + Assert.assertNull(testEntry.getField("author")); + Assert.assertNull(testEntry.getField("title")); + + testEntry = entries.get(2); + Assert.assertEquals("book", testEntry.getType()); + Assert.assertEquals( + "This is a Testtitle: This title should be appended: This title should also be appended. Another append to the Title? LastTitle", + testEntry.getField("title")); + + testEntry = entries.get(3); + Assert.assertEquals("techreport", testEntry.getType()); + Assert.assertNotNull(testEntry.getField("doi")); + + testEntry = entries.get(4); + Assert.assertEquals("inproceedings", testEntry.getType()); + Assert.assertEquals("Inproceedings book title", testEntry.getField("booktitle")); + + BibEntry expectedEntry5 = new BibEntry(); + expectedEntry5.setType("proceedings"); + expectedEntry5.setField("keywords", "Female"); + BibtexEntryAssert.assertEquals(expectedEntry5, entries.get(5)); + + BibEntry expectedEntry6 = new BibEntry(); + expectedEntry6.setType("misc"); + expectedEntry6.setField("keywords", "Female"); + BibtexEntryAssert.assertEquals(expectedEntry6, entries.get(6)); } @Test public void testEmptyFileImport() throws IOException { - List emptyEntries = importer.importDatabase(emptyFileStream).getDatabase().getEntries(); + List emptyEntries = importer.importDatabase(readerForString("")).getDatabase().getEntries(); Assert.assertEquals(Collections.emptyList(), emptyEntries); } @Test - public void testImportSingleEntriesInSingleFiles() throws IOException { + public void testImportSingleEntriesInSingleFiles() throws IOException, URISyntaxException { List testFiles = Arrays.asList("MedlinePlainImporterTestCompleteEntry", "MedlinePlainImporterTestMultiAbstract", "MedlinePlainImporterTestMultiTitle", "MedlinePlainImporterTestDOI", "MedlinePlainImporterTestInproceeding"); @@ -128,10 +128,11 @@ public void testImportSingleEntriesInSingleFiles() throws IOException { } } - private void assertImportOfMedlineFileEqualsBibtexFile(String medlineFile, String bibtexFile) throws IOException { - try (InputStream is = MedlinePlainImporter.class.getResourceAsStream(medlineFile); - InputStream nis = MedlinePlainImporter.class.getResourceAsStream(bibtexFile)) { - List entries = importer.importDatabase(is).getDatabase().getEntries(); + private void assertImportOfMedlineFileEqualsBibtexFile(String medlineFile, String bibtexFile) + throws IOException, URISyntaxException { + Path file = Paths.get(MedlinePlainImporter.class.getResource(medlineFile).toURI()); + try (InputStream nis = MedlinePlainImporter.class.getResourceAsStream(bibtexFile)) { + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertNotNull(entries); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(nis, entries.get(0)); @@ -140,27 +141,27 @@ private void assertImportOfMedlineFileEqualsBibtexFile(String medlineFile, Strin @Test public void testMultiLineComments() throws IOException { - try (InputStream stream = streamForString("PMID-22664220" + "\n" + "CON - Comment1" + "\n" + "CIN - Comment2" - + "\n" + "EIN - Comment3" + "\n" + "EFR - Comment4" + "\n" + "CRI - Comment5" + "\n" + "CRF - Comment6" - + "\n" + "PRIN- Comment7" + "\n" + "PROF- Comment8" + "\n" + "RPI - Comment9" + "\n" + "RPF - Comment10" - + "\n" + "RIN - Comment11" + "\n" + "ROF - Comment12" + "\n" + "UIN - Comment13" + "\n" - + "UOF - Comment14" + "\n" + "SPIN- Comment15" + "\n" + "ORI - Comment16");) { - List actualEntries = importer.importDatabase(stream).getDatabase().getEntries(); - - BibEntry expectedEntry = new BibEntry(); - expectedEntry.setField("comment", - "Comment1" + "\n" + "Comment2" + "\n" + "Comment3" + "\n" + "Comment4" + "\n" + "Comment5" + "\n" - + "Comment6" + "\n" + "Comment7" + "\n" + "Comment8" + "\n" + "Comment9" + "\n" - + "Comment10" + "\n" + "Comment11" + "\n" + "Comment12" + "\n" + "Comment13" + "\n" - + "Comment14" + "\n" + "Comment15" + "\n" + "Comment16"); - BibtexEntryAssert.assertEquals(Arrays.asList(expectedEntry), actualEntries); - } + BufferedReader reader = readerForString( + "PMID-22664220" + "\n" + "CON - Comment1" + "\n" + "CIN - Comment2" + "\n" + "EIN - Comment3" + "\n" + + "EFR - Comment4" + "\n" + "CRI - Comment5" + "\n" + "CRF - Comment6" + "\n" + "PRIN- Comment7" + + "\n" + "PROF- Comment8" + "\n" + "RPI - Comment9" + "\n" + "RPF - Comment10" + "\n" + + "RIN - Comment11" + "\n" + "ROF - Comment12" + "\n" + "UIN - Comment13" + "\n" + + "UOF - Comment14" + "\n" + "SPIN- Comment15" + "\n" + "ORI - Comment16"); + List actualEntries = importer.importDatabase(reader).getDatabase().getEntries(); + + BibEntry expectedEntry = new BibEntry(); + expectedEntry.setField("comment", + "Comment1" + "\n" + "Comment2" + "\n" + "Comment3" + "\n" + "Comment4" + "\n" + "Comment5" + "\n" + + "Comment6" + "\n" + "Comment7" + "\n" + "Comment8" + "\n" + "Comment9" + "\n" + "Comment10" + + "\n" + "Comment11" + "\n" + "Comment12" + "\n" + "Comment13" + "\n" + "Comment14" + "\n" + + "Comment15" + "\n" + "Comment16"); + BibtexEntryAssert.assertEquals(Arrays.asList(expectedEntry), actualEntries); } @Test public void testKeyWords() throws IOException { - try (InputStream stream = streamForString("PMID-22664795" + "\n" + "MH - Female" + "\n" + "OT - Male");) { - List actualEntries = importer.importDatabase(stream).getDatabase().getEntries(); + try (BufferedReader reader = readerForString("PMID-22664795" + "\n" + "MH - Female" + "\n" + "OT - Male")) { + List actualEntries = importer.importDatabase(reader).getDatabase().getEntries(); BibEntry expectedEntry = new BibEntry(); expectedEntry.setField("keywords", "Female, Male"); @@ -170,13 +171,13 @@ public void testKeyWords() throws IOException { @Test public void testAllArticleTypes() throws IOException { - try (InputStream stream = streamForString("PMID-22664795" + "\n" + + try (BufferedReader reader = readerForString("PMID-22664795" + "\n" + "MH - Female\n" + "PT - journal article" + "\n" + "PT - classical article" + "\n" + "PT - corrected and republished article" + "\n" + "PT - introductory journal article" + "\n" + "PT - newspaper article")) { - List actualEntries = importer.importDatabase(stream).getDatabase().getEntries(); + List actualEntries = importer.importDatabase(reader).getDatabase().getEntries(); BibEntry expectedEntry = new BibEntry(); expectedEntry.setType("article"); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java index 7c269aea5a13..de4d18d692fd 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java @@ -1,19 +1,22 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + public class MsBibImporterTest { @Before @@ -27,28 +30,24 @@ public final void testIsNotRecognizedFormat() throws Exception { List notAccepted = Arrays.asList("CopacImporterTest1.txt", "IsiImporterTest1.isi", "IsiImporterTestInspec.isi", "emptyFile.xml", "IsiImporterTestWOS.isi"); for (String s : notAccepted) { - try (InputStream stream = MsBibImporter.class.getResourceAsStream(s)) { - Assert.assertFalse(testImporter.isRecognizedFormat(stream)); - } + Path file = Paths.get(MsBibImporter.class.getResource(s).toURI()); + Assert.assertFalse(testImporter.isRecognizedFormat(file, Charset.defaultCharset())); } - } @Test - public final void testImportEntriesEmpty() throws IOException { + public final void testImportEntriesEmpty() throws IOException, URISyntaxException { MsBibImporter testImporter = new MsBibImporter(); - - List entries = testImporter.importDatabase( - MsBibImporterTest.class.getResourceAsStream("MsBibImporterTest.xml")).getDatabase().getEntries(); + Path file = Paths.get(MsBibImporter.class.getResource("MsBibImporterTest.xml").toURI()); + List entries = testImporter.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(Collections.emptyList(), entries); } @Test - public final void testImportEntriesNotRecognizedFormat() throws IOException { + public final void testImportEntriesNotRecognizedFormat() throws IOException, URISyntaxException { MsBibImporter testImporter = new MsBibImporter(); - - List entries = testImporter.importDatabase( - MsBibImporterTest.class.getResourceAsStream("CopacImporterTest1.txt")).getDatabase().getEntries(); + Path file = Paths.get(MsBibImporter.class.getResource("CopacImporterTest1.txt").toURI()); + List entries = testImporter.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(0, entries.size()); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java index cf6b56ee1769..968aa54372bf 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java @@ -1,22 +1,26 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.bibtex.BibtexEntryAssert; +import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.model.entry.BibEntry; @RunWith(Parameterized.class) public class MsBibImporterTestfiles { @@ -24,10 +28,12 @@ public class MsBibImporterTestfiles { @Parameter public String fileName; + private Path xmlFile; - @BeforeClass - public static void setUp() { + @Before + public void setUp() throws URISyntaxException { Globals.prefs = JabRefPreferences.getInstance(); + xmlFile = Paths.get(MsBibImporter.class.getResource(fileName + ".xml").toURI()); } @Parameters(name = "{index}: {0}") @@ -40,23 +46,18 @@ public static Collection fileNames() { @Test public final void testIsRecognizedFormat() throws Exception { - String xmlFileName = fileName + ".xml"; MsBibImporter testImporter = new MsBibImporter(); - try (InputStream stream = MsBibImporter.class.getResourceAsStream(xmlFileName)) { - Assert.assertTrue(testImporter.isRecognizedFormat(stream)); - } + Assert.assertTrue(testImporter.isRecognizedFormat(xmlFile, Charset.defaultCharset())); } @Test public void testImportEntries() throws IOException { - String xmlFileName = fileName + ".xml"; + String bibFileName = fileName + ".bib"; MsBibImporter testImporter = new MsBibImporter(); - try (InputStream is = MsBibImporter.class.getResourceAsStream(xmlFileName)) { - List result = testImporter.importDatabase(is).getDatabase().getEntries(); - BibtexEntryAssert.assertEquals(MsBibImporterTest.class, bibFileName, result); - } + List result = testImporter.importDatabase(xmlFile, Charset.defaultCharset()).getDatabase().getEntries(); + BibtexEntryAssert.assertEquals(MsBibImporterTest.class, bibFileName, result); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index b156b4a6685d..1b3f4a5ea366 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -2,19 +2,23 @@ import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + public class OvidImporterTest { private OvidImporter importer; @@ -37,110 +41,102 @@ public void testGetCLIId() { } @Test - public void testIsRecognizedFormatAccept() throws IOException { + public void testIsRecognizedFormatAccept() throws IOException, URISyntaxException { List list = Arrays.asList("OvidImporterTest1.txt", "OvidImporterTest3.txt", "OvidImporterTest4.txt", "OvidImporterTest5.txt", "OvidImporterTest6.txt", "OvidImporterTest7.txt"); for (String str : list) { - try (InputStream is = OvidImporter.class.getResourceAsStream(str)) { - Assert.assertTrue(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(OvidImporter.class.getResource(str).toURI()); + Assert.assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testIsRecognizedFormatRejected() throws IOException { + public void testIsRecognizedFormatRejected() throws IOException, URISyntaxException { List list = Arrays.asList("Empty.txt", "OvidImporterTest2.txt"); for (String str : list) { - try (InputStream is = OvidImporter.class.getResourceAsStream(str)) { - Assert.assertFalse(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(OvidImporter.class.getResource(str).toURI()); + Assert.assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public void testImportEmpty() throws IOException { - - try (InputStream is = OvidImporter.class.getResourceAsStream("Empty.txt")) { - List entries = importer.importDatabase(is).getDatabase().getEntries(); - Assert.assertEquals(Collections.emptyList(), entries); - } + public void testImportEmpty() throws IOException, URISyntaxException { + Path file = Paths.get(OvidImporter.class.getResource("Empty.txt").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(Collections.emptyList(), entries); } @Test - public void testImportEntries1() throws IOException { - - try (InputStream is = OvidImporter.class.getResourceAsStream("OvidImporterTest1.txt")) { - List entries = importer.importDatabase(is).getDatabase().getEntries(); - Assert.assertEquals(5, entries.size()); - - BibEntry entry = entries.get(0); - Assert.assertEquals("misc", entry.getType()); - Assert.assertEquals("Mustermann and Musterfrau", entry.getField("author")); - Assert.assertEquals("Short abstract", entry.getField("abstract")); - Assert.assertEquals("Musterbuch", entry.getField("title")); - Assert.assertEquals("Einleitung", entry.getField("chaptertitle")); - - entry = entries.get(1); - Assert.assertEquals("inproceedings", entry.getType()); - Assert.assertEquals("Max", entry.getField("editor")); - Assert.assertEquals("Max the Editor", entry.getField("title")); - Assert.assertEquals("Very Long Title", entry.getField("journal")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("2", entry.getField("issue")); - Assert.assertEquals("2015", entry.getField("year")); - Assert.assertEquals("103--106", entry.getField("pages")); - - entry = entries.get(2); - Assert.assertEquals("incollection", entry.getType()); - Assert.assertEquals("Max", entry.getField("author")); - Assert.assertEquals("Test", entry.getField("title")); - Assert.assertEquals("Very Long Title", entry.getField("journal")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("2", entry.getField("issue")); - Assert.assertEquals("April", entry.getField("month")); - Assert.assertEquals("2015", entry.getField("year")); - Assert.assertEquals("103--106", entry.getField("pages")); - - entry = entries.get(3); - Assert.assertEquals("book", entry.getType()); - Assert.assertEquals("Max", entry.getField("author")); - Assert.assertEquals("2015", entry.getField("year")); - Assert.assertEquals("Editor", entry.getField("editor")); - Assert.assertEquals("Very Long Title", entry.getField("booktitle")); - Assert.assertEquals("103--106", entry.getField("pages")); - Assert.assertEquals("Address", entry.getField("address")); - Assert.assertEquals("Publisher", entry.getField("publisher")); - - entry = entries.get(4); - Assert.assertEquals("article", entry.getType()); - Assert.assertEquals("2014", entry.getField("year")); - Assert.assertEquals("58", entry.getField("pages")); - Assert.assertEquals("Test", entry.getField("address")); - Assert.assertNull(entry.getField("title")); - Assert.assertEquals("TestPublisher", entry.getField("publisher")); - } + public void testImportEntries1() throws IOException, URISyntaxException { + Path file = Paths.get(OvidImporter.class.getResource("OvidImporterTest1.txt").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(5, entries.size()); + + BibEntry entry = entries.get(0); + Assert.assertEquals("misc", entry.getType()); + Assert.assertEquals("Mustermann and Musterfrau", entry.getField("author")); + Assert.assertEquals("Short abstract", entry.getField("abstract")); + Assert.assertEquals("Musterbuch", entry.getField("title")); + Assert.assertEquals("Einleitung", entry.getField("chaptertitle")); + + entry = entries.get(1); + Assert.assertEquals("inproceedings", entry.getType()); + Assert.assertEquals("Max", entry.getField("editor")); + Assert.assertEquals("Max the Editor", entry.getField("title")); + Assert.assertEquals("Very Long Title", entry.getField("journal")); + Assert.assertEquals("28", entry.getField("volume")); + Assert.assertEquals("2", entry.getField("issue")); + Assert.assertEquals("2015", entry.getField("year")); + Assert.assertEquals("103--106", entry.getField("pages")); + + entry = entries.get(2); + Assert.assertEquals("incollection", entry.getType()); + Assert.assertEquals("Max", entry.getField("author")); + Assert.assertEquals("Test", entry.getField("title")); + Assert.assertEquals("Very Long Title", entry.getField("journal")); + Assert.assertEquals("28", entry.getField("volume")); + Assert.assertEquals("2", entry.getField("issue")); + Assert.assertEquals("April", entry.getField("month")); + Assert.assertEquals("2015", entry.getField("year")); + Assert.assertEquals("103--106", entry.getField("pages")); + + entry = entries.get(3); + Assert.assertEquals("book", entry.getType()); + Assert.assertEquals("Max", entry.getField("author")); + Assert.assertEquals("2015", entry.getField("year")); + Assert.assertEquals("Editor", entry.getField("editor")); + Assert.assertEquals("Very Long Title", entry.getField("booktitle")); + Assert.assertEquals("103--106", entry.getField("pages")); + Assert.assertEquals("Address", entry.getField("address")); + Assert.assertEquals("Publisher", entry.getField("publisher")); + + entry = entries.get(4); + Assert.assertEquals("article", entry.getType()); + Assert.assertEquals("2014", entry.getField("year")); + Assert.assertEquals("58", entry.getField("pages")); + Assert.assertEquals("Test", entry.getField("address")); + Assert.assertNull(entry.getField("title")); + Assert.assertEquals("TestPublisher", entry.getField("publisher")); } @Test - public void testImportEntries2() throws IOException { - - try (InputStream is = OvidImporter.class.getResourceAsStream("OvidImporterTest2.txt")) { - List entries = importer.importDatabase(is).getDatabase().getEntries(); - Assert.assertEquals(Collections.emptyList(), entries); - } + public void testImportEntries2() throws IOException, URISyntaxException { + Path file = Paths.get(OvidImporter.class.getResource("OvidImporterTest2.txt").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(Collections.emptyList(), entries); } @Test - public void testImportSingleEntries() throws IOException { + public void testImportSingleEntries() throws IOException, URISyntaxException { for (int n = 3; n <= 7; n++) { - try (InputStream is = OvidImporter.class.getResourceAsStream("OvidImporterTest" + n + ".txt"); - InputStream nis = OvidImporter.class.getResourceAsStream("OvidImporterTestBib" + n + ".bib")) { - List entries = importer.importDatabase(is).getDatabase().getEntries(); + Path file = Paths.get(OvidImporter.class.getResource("OvidImporterTest" + n + ".txt").toURI()); + try (InputStream nis = OvidImporter.class.getResourceAsStream("OvidImporterTestBib" + n + ".bib")) { + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertNotNull(entries); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(nis, entries.get(0)); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java index 2ec3d8d14e6f..3e853d66c09f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java @@ -1,25 +1,27 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.model.entry.BibEntry; - -import org.junit.Test; - import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import java.util.List; -import static org.junit.Assert.*; +import net.sf.jabref.model.entry.BibEntry; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; public class PdfContentImporterTest { @Test - public void doesNotHandleEncryptedPdfs() throws IOException { + public void doesNotHandleEncryptedPdfs() throws IOException, URISyntaxException { PdfContentImporter importer = new PdfContentImporter(); - try (InputStream is = PdfContentImporter.class.getResourceAsStream("/pdfs/encrypted.pdf")) { - List result = importer.importDatabase(is).getDatabase().getEntries(); - assertEquals(Collections.emptyList(), result); - } + Path file = Paths.get(PdfContentImporter.class.getResource("/pdfs/encrypted.pdf").toURI()); + List result = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + assertEquals(Collections.emptyList(), result); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java index c562b75dd5f4..362e1fb83625 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java @@ -1,11 +1,19 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.bibtex.BibtexEntryAssert; +import net.sf.jabref.model.entry.BibEntry; + import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -13,11 +21,6 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.model.entry.BibEntry; - @RunWith(Parameterized.class) public class PdfContentImporterTestFiles { @@ -43,14 +46,13 @@ public static Collection fileNames() { } @Test - public void correctContent() throws IOException { + public void correctContent() throws IOException, URISyntaxException { String pdfFileName = fileName + ".pdf"; String bibFileName = fileName + ".bib"; PdfContentImporter importer = new PdfContentImporter(); - try (InputStream is = PdfContentImporter.class.getResourceAsStream(pdfFileName)) { - List result = importer.importDatabase(is).getDatabase().getEntries(); - BibtexEntryAssert.assertEquals(PdfContentImporterTest.class, bibFileName, result); - } + Path pdfFile = Paths.get(PdfContentImporter.class.getResource(pdfFileName).toURI()); + List result = importer.importDatabase(pdfFile, Charset.defaultCharset()).getDatabase().getEntries(); + BibtexEntryAssert.assertEquals(PdfContentImporterTest.class, bibFileName, result); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index 23cc6f3240bc..ae3bfd840815 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -1,7 +1,10 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; @@ -35,44 +38,40 @@ public void testGetFormatName() { } @Test - public void importEncryptedFileReturnsError() throws IOException { - try (InputStream is = PdfXmpImporterTest.class.getResourceAsStream("/pdfs/encrypted.pdf")) { - ParserResult result = importer.importDatabase(is); - Assert.assertTrue(result.hasWarnings()); - } + public void importEncryptedFileReturnsError() throws IOException, URISyntaxException { + Path file = Paths.get(PdfXmpImporterTest.class.getResource("/pdfs/encrypted.pdf").toURI()); + ParserResult result = importer.importDatabase(file, Charset.defaultCharset()); + Assert.assertTrue(result.hasWarnings()); } @Test - public void testImportEntries() throws IOException { - try (InputStream is = PdfXmpImporterTest.class.getResourceAsStream("annotated.pdf")) { - List bibEntries = importer.importDatabase(is).getDatabase().getEntries(); + public void testImportEntries() throws IOException, URISyntaxException { + Path file = Paths.get(PdfXmpImporterTest.class.getResource("annotated.pdf").toURI()); + List bibEntries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); - assertEquals(1, bibEntries.size()); + assertEquals(1, bibEntries.size()); - BibEntry be0 = bibEntries.get(0); - assertEquals("how to annotate a pdf", be0.getField("abstract")); - assertEquals("Chris", be0.getField("author")); - assertEquals("pdf, annotation", be0.getField("keywords")); - assertEquals("The best Pdf ever", be0.getField("title")); - } + BibEntry be0 = bibEntries.get(0); + assertEquals("how to annotate a pdf", be0.getField("abstract")); + assertEquals("Chris", be0.getField("author")); + assertEquals("pdf, annotation", be0.getField("keywords")); + assertEquals("The best Pdf ever", be0.getField("title")); } @Test - public void testIsRecognizedFormat() throws IOException { - try (InputStream is = PdfXmpImporterTest.class.getResourceAsStream("annotated.pdf")) { - assertTrue(importer.isRecognizedFormat(is)); - } + public void testIsRecognizedFormat() throws IOException, URISyntaxException { + Path file = Paths.get(PdfXmpImporterTest.class.getResource("annotated.pdf").toURI()); + assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); } @Test - public void testIsRecognizedFormatReject() throws IOException { + public void testIsRecognizedFormatReject() throws IOException, URISyntaxException { List list = Arrays.asList("IEEEImport1.txt", "IsiImporterTest1.isi", "IsiImporterTestInspec.isi", "IsiImporterTestWOS.isi", "IsiImporterTestMedline.isi", "RisImporterTest1.ris", "empty.pdf"); for (String str : list) { - try (InputStream is = PdfXmpImporterTest.class.getResourceAsStream(str)) { - assertFalse(importer.isRecognizedFormat(is)); - } + Path file = Paths.get(PdfXmpImporterTest.class.getResource(str).toURI()); + assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java index 78e636ad76b8..75a0f683acc9 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java @@ -1,9 +1,13 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.*; - import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import org.junit.Assert; import org.junit.Before; @@ -31,10 +35,9 @@ public void testGetCLIId() { } @Test - public void testIfNotRecognizedFormat() throws IOException { - try (InputStream stream = RISImporterTest.class.getResourceAsStream("RisImporterCorrupted.ris")) { - Assert.assertFalse(risImporter.isRecognizedFormat(stream)); - } + public void testIfNotRecognizedFormat() throws IOException, URISyntaxException { + Path file = Paths.get(RISImporterTest.class.getResource("RisImporterCorrupted.ris").toURI()); + Assert.assertFalse(risImporter.isRecognizedFormat(file, Charset.defaultCharset())); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java index 290a6e06f41b..642f900a8511 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java @@ -1,8 +1,19 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.*; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.bibtex.BibtexEntryAssert; import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -11,12 +22,6 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - @RunWith(Parameterized.class) public class RISImporterTestFiles { @@ -25,34 +30,29 @@ public class RISImporterTestFiles { @Parameter public String fileName; + private Path risFile; @Before - public void setUp() { + public void setUp() throws URISyntaxException { Globals.prefs = JabRefPreferences.getInstance(); risImporter = new RisImporter(); + risFile = Paths.get(RISImporterTest.class.getResource(fileName + ".ris").toURI()); } @Parameters(name = "{0}") public static Collection fileNames() { - return Arrays - .asList(new String[] {"RisImporterTest1", "RisImporterTest3", "RisImporterTest4a", "RisImporterTest4b", - "RisImporterTest4c", "RisImporterTest5a", "RisImporterTest5b", "RisImporterTest6"}); + return Arrays.asList("RisImporterTest1", "RisImporterTest3", "RisImporterTest4a", "RisImporterTest4b", + "RisImporterTest4c", "RisImporterTest5a", "RisImporterTest5b", "RisImporterTest6"); } @Test public void testIsRecognizedFormat() throws IOException { - try (InputStream stream = RISImporterTest.class.getResourceAsStream(fileName + ".ris")) { - Assert.assertTrue(risImporter.isRecognizedFormat(stream)); - } + Assert.assertTrue(risImporter.isRecognizedFormat(risFile, Charset.defaultCharset())); } @Test public void testImportEntries() throws IOException { - try (InputStream risStream = RISImporterTest.class.getResourceAsStream(fileName + ".ris")) { - - List risEntries = risImporter.importDatabase(risStream).getDatabase().getEntries(); - BibtexEntryAssert.assertEquals(RISImporterTest.class, fileName + ".bib", risEntries); - - } + List risEntries = risImporter.importDatabase(risFile, Charset.defaultCharset()).getDatabase().getEntries(); + BibtexEntryAssert.assertEquals(RISImporterTest.class, fileName + ".bib", risEntries); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index 30cb24a1e2ea..405657206a50 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -2,6 +2,10 @@ import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; @@ -26,52 +30,50 @@ public void setUp() { } @Test - public final void testIsRecognizedFormat() throws IOException { + public final void testIsRecognizedFormat() throws IOException, URISyntaxException { List accepted = Arrays.asList("RepecNepImporterTest1.txt", "RepecNepImporterTest2.txt", "RepecNepImporterTest3.txt"); for (String s : accepted) { - try (InputStream stream = RepecNepImporter.class.getResourceAsStream(s)) { - Assert.assertTrue(testImporter.isRecognizedFormat(stream)); - } + Path file = Paths.get(RepecNepImporter.class.getResource(s).toURI()); + Assert.assertTrue(testImporter.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public final void testIsNotRecognizedFormat() throws IOException { + public final void testIsNotRecognizedFormat() throws IOException, URISyntaxException { List notAccepted = Arrays.asList("RepecNep1.xml", "CopacImporterTest1.txt", "RisImporterTest1.ris", "CopacImporterTest2.txt", "IEEEImport1.txt"); for (String s : notAccepted) { - try (InputStream stream = RepecNepImporter.class.getResourceAsStream(s)) { - Assert.assertFalse(testImporter.isRecognizedFormat(stream)); - } + Path file = Paths.get(RepecNepImporter.class.getResource(s).toURI()); + Assert.assertFalse(testImporter.isRecognizedFormat(file, Charset.defaultCharset())); } } @Test - public final void testImportEntries1() throws IOException { - try (InputStream in = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest1.txt"); - InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest1.bib")) { - List entries = testImporter.importDatabase(in).getDatabase().getEntries(); + public final void testImportEntries1() throws IOException, URISyntaxException { + Path file = Paths.get(RepecNepImporter.class.getResource("RepecNepImporterTest1.txt").toURI()); + try (InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest1.bib")) { + List entries = testImporter.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(bibIn, entries.get(0)); } } @Test - public final void testImportEntries2() throws IOException { - try (InputStream in = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest2.txt"); - InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest2.bib")) { - List entries = testImporter.importDatabase(in).getDatabase().getEntries(); + public final void testImportEntries2() throws IOException, URISyntaxException { + Path file = Paths.get(RepecNepImporter.class.getResource("RepecNepImporterTest2.txt").toURI()); + try (InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest2.bib")) { + List entries = testImporter.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(bibIn, entries.get(0)); } } @Test - public final void testImportEntries3() throws IOException { - try (InputStream in = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest3.txt"); - InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest3.bib")) { - List entries = testImporter.importDatabase(in).getDatabase().getEntries(); + public final void testImportEntries3() throws IOException, URISyntaxException { + Path file = Paths.get(RepecNepImporter.class.getResource("RepecNepImporterTest3.txt").toURI()); + try (InputStream bibIn = RepecNepImporter.class.getResourceAsStream("RepecNepImporterTest3.bib")) { + List entries = testImporter.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibtexEntryAssert.assertEquals(bibIn, entries.get(0)); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java index e1d459716a92..f541e6efc77e 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java @@ -1,10 +1,18 @@ package net.sf.jabref.importer.fileformat; import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.bibtex.BibtexEntryAssert; +import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -13,11 +21,6 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.model.entry.BibEntry; - @RunWith(Parameterized.class) public class SilverPlatterImporterTest { @@ -26,7 +29,7 @@ public class SilverPlatterImporterTest { @Parameter public String filename; - public String txtName; + public Path txtFile; public String bibName; @@ -34,7 +37,7 @@ public class SilverPlatterImporterTest { public void setUp() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); testImporter = new SilverPlatterImporter(); - txtName = filename + ".txt"; + txtFile = Paths.get(SilverPlatterImporterTest.class.getResource(filename + ".txt").toURI()); bibName = filename + ".bib"; } @@ -46,16 +49,13 @@ public static Collection fileNames() { @Test public final void testIsRecognizedFormat() throws Exception { - try (InputStream stream = SilverPlatterImporterTest.class.getResourceAsStream(txtName)) { - Assert.assertTrue(testImporter.isRecognizedFormat(stream)); - } + Assert.assertTrue(testImporter.isRecognizedFormat(txtFile, Charset.defaultCharset())); } @Test public final void testImportEntries() throws Exception { - try (InputStream in = SilverPlatterImporter.class.getResourceAsStream(txtName); - InputStream bibIn = SilverPlatterImporterTest.class.getResourceAsStream(bibName)) { - List entries = testImporter.importDatabase(in).getDatabase().getEntries(); + try (InputStream bibIn = SilverPlatterImporterTest.class.getResourceAsStream(bibName)) { + List entries = testImporter.importDatabase(txtFile, Charset.defaultCharset()).getDatabase().getEntries(); BibtexEntryAssert.assertEquals(bibIn, entries); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java index 2e0572f42928..b16cf50b0e40 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java @@ -1,16 +1,18 @@ package net.sf.jabref.importer.fileformat; -import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; - public class SilverPlatterImporterTestNotRecognized { public SilverPlatterImporter testImporter; @@ -27,9 +29,8 @@ public final void testIsNotRecognizedFormat() throws Exception { List notAccept = Arrays.asList("emptyFile.xml", "IsiImporterTest1.isi", "InspecSilverPlatterImporterTest.txt", "oai2.xml", "RisImporterTest1.ris"); for (String s : notAccept) { - try (InputStream stream = SilverPlatterImporter.class.getResourceAsStream(s)) { - Assert.assertFalse(testImporter.isRecognizedFormat(stream)); - } + Path file = Paths.get(SilverPlatterImporter.class.getResource(s).toURI()); + Assert.assertFalse(testImporter.isRecognizedFormat(file, Charset.defaultCharset())); } } From 1c509b198672d56d5f7313819a00b44000d99589 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 14 Apr 2016 13:12:52 +0200 Subject: [PATCH 005/268] Move code from OpenDatabaseAction to BibtexImporter --- .../jabref/importer/ImportFormatReader.java | 44 +----- .../sf/jabref/importer/ImportMenuItem.java | 2 +- .../jabref/importer/OpenDatabaseAction.java | 133 ++++-------------- .../importer/fileformat/BibtexImporter.java | 70 +++++++++ .../importer/fileformat/ImportFormat.java | 34 +++-- .../exporter/BibDatabaseWriterTest.java | 26 ++-- .../logic/openoffice/OOBibStyleTest.java | 26 ++-- 7 files changed, 151 insertions(+), 184 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java index c0b4b1fcaeec..27e16e243bb8 100644 --- a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java +++ b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java @@ -15,14 +15,7 @@ */ package net.sf.jabref.importer; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; @@ -130,18 +123,7 @@ public ParserResult importFromFile(String format, Path file) throw new IllegalArgumentException("Unknown import format: " + format); } - return importFromFile(importer.get(), file); - } - - public ParserResult importFromFile(ImportFormat importer, Path file) throws IOException { - Objects.requireNonNull(importer); - Objects.requireNonNull(file); - - if(!importer.isRecognizedFormat(file, Globals.prefs.getDefaultEncoding())) { - throw new IOException("Wrong file format"); - } - - return importer.importDatabase(file, Globals.prefs.getDefaultEncoding()); + return importer.get().importDatabase(file, Globals.prefs.getDefaultEncoding()); } /** @@ -184,28 +166,6 @@ public String getImportFormatList() { return sb.toString(); } - - - public static InputStreamReader getUTF8Reader(File f) throws IOException { - return getReader(f, StandardCharsets.UTF_8); - } - - public static InputStreamReader getUTF16Reader(File f) throws IOException { - return getReader(f, StandardCharsets.UTF_16); - } - - public static InputStreamReader getReader(File f, Charset charset) - throws IOException { - return new InputStreamReader(new FileInputStream(f), charset); - } - - public static Reader getReaderDefaultEncoding(InputStream in) { - InputStreamReader reader; - reader = new InputStreamReader(in, Globals.prefs.getDefaultEncoding()); - - return reader; - } - public static class UnknownFormatImport { public final String format; @@ -257,7 +217,7 @@ public UnknownFormatImport importUnknownFormat(Path file) { continue; } - ParserResult parserResult = importFromFile(imFo, file); + ParserResult parserResult = imFo.importDatabase(file, Globals.prefs.getDefaultEncoding()); List entries = parserResult.getDatabase().getEntries(); BibDatabases.purgeEmptyEntries(entries); diff --git a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java index 090ff070ea91..3956f8d67b99 100644 --- a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java +++ b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java @@ -138,7 +138,7 @@ public void run() { } else { frame.output(Localization.lang("Importing in %0 format", importer.getFormatName()) + "..."); // Specific importer: - ParserResult pr = Globals.IMPORT_FORMAT_READER.importFromFile(importer, file); + ParserResult pr = importer.importDatabase(file, Globals.prefs.getDefaultEncoding()); if (pr.hasWarnings()) { frame.showMessage(pr.getErrorMessage()); } diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index 0921e247b55b..b335d7fd0506 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -16,38 +16,44 @@ package net.sf.jabref.importer; import java.awt.event.ActionEvent; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Optional; import javax.swing.Action; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import net.sf.jabref.*; +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Defaults; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefExecutorService; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.MetaData; import net.sf.jabref.exporter.AutoSaveManager; import net.sf.jabref.exporter.SaveSession; -import net.sf.jabref.gui.*; +import net.sf.jabref.gui.BasePanel; +import net.sf.jabref.gui.FileDialogs; +import net.sf.jabref.gui.IconTheme; +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.ParserResultWarningDialog; import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.undo.NamedCompound; -import net.sf.jabref.migrations.FileLinksUpgradeWarning; -import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.importer.fileformat.BibtexImporter; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.io.FileBasedLock; +import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.migrations.FileLinksUpgradeWarning; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.specialfields.SpecialFieldsUtils; -import net.sf.jabref.logic.util.io.FileBasedLock; -import net.sf.jabref.logic.util.strings.StringUtil; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -328,109 +334,22 @@ public BasePanel addNewDatabase(ParserResult result, final File file, boolean ra * Opens a new database. */ public static ParserResult loadDatabase(File fileToOpen, Charset defaultEncoding) throws IOException { - - // We want to check if there is a JabRef signature in the file, because that would tell us - // which character encoding is used. However, to read the signature we must be using a compatible - // encoding in the first place. Since the signature doesn't contain any fancy characters, we can - // read it regardless of encoding, with either UTF-8 or UTF-16. That's the hypothesis, at any rate. - // 8 bit is most likely, so we try that first: - Optional suppliedEncoding; - try (Reader utf8Reader = ImportFormatReader.getUTF8Reader(fileToOpen)) { - suppliedEncoding = OpenDatabaseAction.getSuppliedEncoding(utf8Reader); - } - // Now if that didn't get us anywhere, we check with the 16 bit encoding: - if (!suppliedEncoding.isPresent()) { - try (Reader utf16Reader = ImportFormatReader.getUTF16Reader(fileToOpen)) { - suppliedEncoding = OpenDatabaseAction.getSuppliedEncoding(utf16Reader); - } - } - // Open and parse file - try (InputStreamReader reader = openFile(fileToOpen, suppliedEncoding, defaultEncoding)) { - BibtexParser parser = new BibtexParser(reader); + ParserResult result = new BibtexImporter().importDatabase(fileToOpen.toPath(), defaultEncoding); - ParserResult result = parser.parse(); - result.setEncoding(Charset.forName(reader.getEncoding())); - result.setFile(fileToOpen); - - if (SpecialFieldsUtils.keywordSyncEnabled()) { - NamedCompound compound = new NamedCompound("SpecialFieldSync"); - for (BibEntry entry : result.getDatabase().getEntries()) { - SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, compound); - } - LOGGER.info("Synchronized special fields based on keywords"); + if (SpecialFieldsUtils.keywordSyncEnabled()) { + NamedCompound compound = new NamedCompound("SpecialFieldSync"); + for (BibEntry entry : result.getDatabase().getEntries()) { + SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, compound); } - - if (!result.getMetaData().isGroupTreeValid()) { - result.addWarning(Localization.lang( - "Group tree could not be parsed. If you save the BibTeX database, all groups will be lost.")); - } - - return result; + LOGGER.info("Synchronized special fields based on keywords"); } - } - - /** - * Opens the file with the provided encoding. If this fails (or no encoding is provided), then the fallback encoding - * will be used. - */ - private static InputStreamReader openFile(File fileToOpen, Optional encoding, Charset defaultEncoding) - throws IOException { - if (encoding.isPresent()) { - try { - return ImportFormatReader.getReader(fileToOpen, encoding.get()); - } catch (IOException ex) { - LOGGER.warn("Problem getting reader", ex); - // The supplied encoding didn't work out, so we use the fallback. - return ImportFormatReader.getReader(fileToOpen, defaultEncoding); - } - } else { - // We couldn't find a header with info about encoding. Use fallback: - return ImportFormatReader.getReader(fileToOpen, defaultEncoding); + if (!result.getMetaData().isGroupTreeValid()) { + result.addWarning(Localization.lang( + "Group tree could not be parsed. If you save the BibTeX database, all groups will be lost.")); } - } - /** - * Searches the file for "Encoding: myEncoding" and returns the found supplied encoding. - */ - private static Optional getSuppliedEncoding(Reader reader) { - try { - BufferedReader bufferedReader = new BufferedReader(reader); - String line; - while ((line = bufferedReader.readLine()) != null) { - line = line.trim(); - - // Line does not start with %, so there are no comment lines for us and we can stop parsing - if (!line.startsWith("%")) { - return Optional.empty(); - } - - // Only keep the part after % - line = line.substring(1).trim(); - - if (line.startsWith(Globals.SIGNATURE)) { - // Signature line, so keep reading and skip to next line - } else if (line.startsWith(Globals.ENCODING_PREFIX)) { - // Line starts with "Encoding: ", so the rest of the line should contain the name of the encoding - // Except if there is already a @ symbol signaling the starting of a BibEntry - Integer atSymbolIndex = line.indexOf('@'); - String encoding; - if (atSymbolIndex > 0) { - encoding = line.substring(Globals.ENCODING_PREFIX.length(), atSymbolIndex); - } else { - encoding = line.substring(Globals.ENCODING_PREFIX.length()); - } - - return Optional.of(Charset.forName(encoding)); - } else { - // Line not recognized so stop parsing - return Optional.empty(); - } - } - } catch (IOException ignored) { - // Ignored - } - return Optional.empty(); + return result; } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java index 9ec223becdfb..f84f9e8df254 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java @@ -17,10 +17,14 @@ import java.io.BufferedReader; import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; +import net.sf.jabref.Globals; import net.sf.jabref.importer.ParserResult; /** @@ -41,6 +45,31 @@ public boolean isRecognizedFormat(BufferedReader reader) { return true; } + @Override + public ParserResult importDatabase(Path filePath, Charset defaultEncoding) throws IOException { + // We want to check if there is a JabRef signature in the file, because that would tell us + // which character encoding is used. However, to read the signature we must be using a compatible + // encoding in the first place. Since the signature doesn't contain any fancy characters, we can + // read it regardless of encoding, with either UTF-8 or UTF-16. That's the hypothesis, at any rate. + // 8 bit is most likely, so we try that first: + Optional suppliedEncoding; + try (BufferedReader utf8Reader = getUTF8Reader(filePath)) { + suppliedEncoding = getSuppliedEncoding(utf8Reader); + } + // Now if that didn't get us anywhere, we check with the 16 bit encoding: + if (!suppliedEncoding.isPresent()) { + try (BufferedReader utf16Reader = getUTF16Reader(filePath)) { + suppliedEncoding = getSuppliedEncoding(utf16Reader); + } + } + + if(suppliedEncoding.isPresent()) { + return super.importDatabase(filePath, suppliedEncoding.get()); + } else { + return super.importDatabase(filePath, defaultEncoding); + } + } + @Override public ParserResult importDatabase(BufferedReader reader) throws IOException { return BibtexParser.parse(reader); @@ -61,4 +90,45 @@ public String getDescription() { return null; } + /** + * Searches the file for "Encoding: myEncoding" and returns the found supplied encoding. + */ + private static Optional getSuppliedEncoding(BufferedReader reader) { + try { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + + // Line does not start with %, so there are no comment lines for us and we can stop parsing + if (!line.startsWith("%")) { + return Optional.empty(); + } + + // Only keep the part after % + line = line.substring(1).trim(); + + if (line.startsWith(Globals.SIGNATURE)) { + // Signature line, so keep reading and skip to next line + } else if (line.startsWith(Globals.ENCODING_PREFIX)) { + // Line starts with "Encoding: ", so the rest of the line should contain the name of the encoding + // Except if there is already a @ symbol signaling the starting of a BibEntry + Integer atSymbolIndex = line.indexOf('@'); + String encoding; + if (atSymbolIndex > 0) { + encoding = line.substring(Globals.ENCODING_PREFIX.length(), atSymbolIndex); + } else { + encoding = line.substring(Globals.ENCODING_PREFIX.length()); + } + + return Optional.of(Charset.forName(encoding)); + } else { + // Line not recognized so stop parsing + return Optional.empty(); + } + } + } catch (IOException ignored) { + // Ignored + } + return Optional.empty(); + } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java index 2c50926da2d5..0c4887630bf4 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -52,10 +53,8 @@ public abstract class ImportFormat implements Comparable { */ protected abstract boolean isRecognizedFormat(BufferedReader input) throws IOException; - public boolean isRecognizedFormat(Path filePath, Charset defaultEncoding) throws IOException { - try (InputStream stream = new FileInputStream(filePath.toFile()); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, defaultEncoding))) { - + public boolean isRecognizedFormat(Path filePath, Charset encoding) throws IOException { + try (BufferedReader bufferedReader = getReader(filePath, encoding)) { return isRecognizedFormat(bufferedReader); } } @@ -84,16 +83,31 @@ public boolean isRecognizedFormat(Path filePath, Charset defaultEncoding) throws * determine the encoding and then call {@link #importDatabase(BufferedReader)}. * * @param filePath the path to the file which should be imported - * @param defaultEncoding the encoding used by default to decode the file + * @param encoding the encoding used to decode the file */ - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) throws IOException { - try (InputStream stream = new FileInputStream(filePath.toFile()); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, defaultEncoding))) { - - return importDatabase(bufferedReader); + public ParserResult importDatabase(Path filePath, Charset encoding) throws IOException { + try (BufferedReader bufferedReader = getReader(filePath, encoding)) { + ParserResult parserResult = importDatabase(bufferedReader); + parserResult.setEncoding(encoding); + parserResult.setFile(filePath.toFile()); + return parserResult; } } + public static BufferedReader getUTF8Reader(Path filePath) throws IOException { + return getReader(filePath, StandardCharsets.UTF_8); + } + + public static BufferedReader getUTF16Reader(Path filePath) throws IOException { + return getReader(filePath, StandardCharsets.UTF_16); + } + + public static BufferedReader getReader(Path filePath, Charset encoding) + throws IOException { + InputStream stream = new FileInputStream(filePath.toFile()); + return new BufferedReader(new InputStreamReader(stream, encoding)); + } + /** * Returns the name of this import format. * diff --git a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java index 3f0c13959946..89a6b3f13d33 100644 --- a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java @@ -1,24 +1,16 @@ package net.sf.jabref.exporter; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; - -import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.Scanner; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.google.common.base.Charsets; - import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; import net.sf.jabref.Globals; @@ -28,9 +20,9 @@ import net.sf.jabref.groups.structure.AllEntriesGroup; import net.sf.jabref.groups.structure.ExplicitGroup; import net.sf.jabref.groups.structure.GroupHierarchyType; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.logic.formatter.casechanger.LowerCaseFormatter; @@ -45,6 +37,14 @@ import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.IdGenerator; +import com.google.common.base.Charsets; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; + public class BibDatabaseWriterTest { private BibDatabaseWriter databaseWriter; @@ -276,9 +276,9 @@ public void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws IOExc @Test public void roundtrip() throws IOException { - File testBibtexFile = new File("src/test/resources/testbib/complex.bib"); + Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); Charset encoding = StandardCharsets.UTF_8; - ParserResult result = BibtexParser.parse(ImportFormatReader.getReader(testBibtexFile, encoding)); + ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); SavePreferences preferences = new SavePreferences().withEncoding(encoding).withSaveInOriginalOrder(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), diff --git a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java index 6d3923440574..6dc6e62d475c 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java @@ -1,10 +1,10 @@ package net.sf.jabref.logic.openoffice; -import static org.junit.Assert.*; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -13,21 +13,25 @@ import java.util.Map; import java.util.Set; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - import net.sf.jabref.Globals; import net.sf.jabref.JabRef; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.logic.journals.JournalAbbreviationRepository; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; public class OOBibStyleTest { @@ -139,8 +143,8 @@ public void testGetCitProperty() throws IOException { @Test public void testGetCitationMarker() throws IOException { - File testBibtexFile = new File("src/test/resources/testbib/complex.bib"); - ParserResult result = BibtexParser.parse(ImportFormatReader.getReader(testBibtexFile, StandardCharsets.UTF_8)); + Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); + ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, mock(JournalAbbreviationRepository.class)); Map entryDBMap = new HashMap<>(); @@ -160,8 +164,8 @@ public void testGetCitationMarker() throws IOException { @Test public void testLayout() throws IOException { - File testBibtexFile = new File("src/test/resources/testbib/complex.bib"); - ParserResult result = BibtexParser.parse(ImportFormatReader.getReader(testBibtexFile, StandardCharsets.UTF_8)); + Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); + ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, mock(JournalAbbreviationRepository.class)); BibDatabase db = result.getDatabase(); @@ -491,4 +495,4 @@ public void testCompareToNotEqual() throws IOException { assertTrue(style1.compareTo(style2) > 0); assertFalse(style2.compareTo(style1) > 0); } -} \ No newline at end of file +} From 8a031fad91e5c278a964db241b70e35c530a0799 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 21 Apr 2016 19:39:04 +0200 Subject: [PATCH 006/268] Improved integrity check dialog --- CHANGELOG.md | 1 + .../java/net/sf/jabref/gui/JabRefFrame.java | 60 +------------ .../net/sf/jabref/gui/actions/Actions.java | 1 - .../gui/actions/IntegrityCheckAction.java | 85 +++++++++++++++++++ .../importer/fileformat/BibtexParser.java | 6 +- src/main/resources/l10n/JabRef_da.properties | 9 +- src/main/resources/l10n/JabRef_de.properties | 9 +- src/main/resources/l10n/JabRef_en.properties | 9 +- src/main/resources/l10n/JabRef_es.properties | 9 +- src/main/resources/l10n/JabRef_fa.properties | 9 +- src/main/resources/l10n/JabRef_fr.properties | 9 +- src/main/resources/l10n/JabRef_in.properties | 9 +- src/main/resources/l10n/JabRef_it.properties | 9 +- src/main/resources/l10n/JabRef_ja.properties | 9 +- src/main/resources/l10n/JabRef_nl.properties | 9 +- src/main/resources/l10n/JabRef_no.properties | 9 +- .../resources/l10n/JabRef_pt_BR.properties | 9 +- src/main/resources/l10n/JabRef_ru.properties | 9 +- src/main/resources/l10n/JabRef_sv.properties | 9 +- src/main/resources/l10n/JabRef_tr.properties | 9 +- src/main/resources/l10n/JabRef_vi.properties | 9 +- src/main/resources/l10n/JabRef_zh.properties | 9 +- 22 files changed, 193 insertions(+), 113 deletions(-) create mode 100644 src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 446d4903eff0..deb47a7c2236 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Implemented [feature request 384](https://sourceforge.net/p/jabref/features/384): The merge entries dialog now show all text and colored differences between the fields - Implemented [#1233](https://github.com/JabRef/jabref/issues/1233): Group side pane now takes up all the remaining space - Added integrity check detecting HTML-encoded characters +- Integrity check table can be sorted by clicking on column headings ### Fixed - Fixed [#1234](https://github.com/JabRef/jabref/issues/1234): NPE when getting information from retrieved DOI diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 5ebbe6c3c767..10d8219abc04 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -58,13 +58,10 @@ import javax.swing.JPopupMenu; import javax.swing.JProgressBar; import javax.swing.JRadioButtonMenuItem; -import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; -import javax.swing.JTable; import javax.swing.JToggleButton; import javax.swing.KeyStroke; -import javax.swing.ListSelectionModel; import javax.swing.MenuElement; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; @@ -88,6 +85,7 @@ import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.actions.AutoLinkFilesAction; import net.sf.jabref.gui.actions.ErrorConsoleAction; +import net.sf.jabref.gui.actions.IntegrityCheckAction; import net.sf.jabref.gui.actions.ManageKeywordsAction; import net.sf.jabref.gui.actions.MassSetFieldAction; import net.sf.jabref.gui.actions.MnemonicAwareAction; @@ -123,8 +121,6 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fetcher.GeneralFetcher; import net.sf.jabref.logic.CustomEntryTypesManager; -import net.sf.jabref.logic.integrity.IntegrityCheck; -import net.sf.jabref.logic.integrity.IntegrityMessage; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.logging.GuiAppender; import net.sf.jabref.logic.preferences.LastFocusedTabPreferences; @@ -173,59 +169,7 @@ public class JabRefFrame extends JFrame implements OutputPrinter { private PositionWindow pw; - private final GeneralAction checkIntegrity = new GeneralAction(Actions.CHECK_INTEGRITY, Localization.menuTitle("Check integrity") + ELLIPSES) { - - @Override - public void actionPerformed(ActionEvent e) { - IntegrityCheck check = new IntegrityCheck(getCurrentBasePanel().getBibDatabaseContext()); - List messages = check.checkBibtexDatabase(); - - if (messages.isEmpty()) { - JOptionPane.showMessageDialog(getCurrentBasePanel(), Localization.lang("No problems found.")); - } else { - // prepare data model - Object[][] model = new Object[messages.size()][3]; - int i = 0; - for (IntegrityMessage message : messages) { - model[i][0] = message.getEntry().getCiteKey(); - model[i][1] = message.getFieldName(); - model[i][2] = message.getMessage(); - i++; - } - - // construct view - JTable table = new JTable( - model, - new Object[] {"key", "field", "message"} - ); - - table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - ListSelectionModel selectionModel = table.getSelectionModel(); - - selectionModel.addListSelectionListener(event -> { - if (!event.getValueIsAdjusting()) { - String citeKey = (String) model[table.getSelectedRow()][0]; - String fieldName = (String) model[table.getSelectedRow()][1]; - getCurrentBasePanel().editEntryByKeyAndFocusField(citeKey, fieldName); - } - }); - - table.getColumnModel().getColumn(0).setPreferredWidth(80); - table.getColumnModel().getColumn(1).setPreferredWidth(30); - table.getColumnModel().getColumn(2).setPreferredWidth(250); - table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); - JScrollPane scrollPane = new JScrollPane(table); - String title = Localization.lang("%0 problem(s) found", String.valueOf(messages.size())); - JDialog dialog = new JDialog(JabRefFrame.this, title, false); - dialog.add(scrollPane); - dialog.setSize(600, 500); - - // show view - dialog.setVisible(true); - } - } - }; - + private final IntegrityCheckAction checkIntegrity = new IntegrityCheckAction(this); private final ToolBar tlb = new ToolBar(); diff --git a/src/main/java/net/sf/jabref/gui/actions/Actions.java b/src/main/java/net/sf/jabref/gui/actions/Actions.java index aea0fd2fbac8..96b5496924b1 100644 --- a/src/main/java/net/sf/jabref/gui/actions/Actions.java +++ b/src/main/java/net/sf/jabref/gui/actions/Actions.java @@ -11,7 +11,6 @@ public class Actions { public static final String ADD_TO_GROUP = "addToGroup"; public static final String AUTO_SET_FILE = "autoSetFile"; public static final String BACK = "back"; - public static final String CHECK_INTEGRITY = "checkIntegrity"; public static final String CLEANUP = "Cleanup"; public static final String COPY = "copy"; public static final String COPY_KEY = "copyKey"; diff --git a/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java b/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java new file mode 100644 index 000000000000..b9757fbe6131 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java @@ -0,0 +1,85 @@ +package net.sf.jabref.gui.actions; + +import java.awt.event.ActionEvent; +import java.util.List; + +import javax.swing.Action; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.logic.integrity.IntegrityCheck; +import net.sf.jabref.logic.integrity.IntegrityMessage; +import net.sf.jabref.logic.l10n.Localization; + +public class IntegrityCheckAction extends MnemonicAwareAction { + + private static final String ELLIPSES = "..."; + + + private final JabRefFrame frame; + + + public IntegrityCheckAction(JabRefFrame frame) { + this.frame = frame; + putValue(Action.NAME, Localization.menuTitle("Check integrity") + ELLIPSES); + } + + @Override + public void actionPerformed(ActionEvent e) { + IntegrityCheck check = new IntegrityCheck(frame.getCurrentBasePanel().getBibDatabaseContext()); + List messages = check.checkBibtexDatabase(); + + if (messages.isEmpty()) { + JOptionPane.showMessageDialog(frame.getCurrentBasePanel(), Localization.lang("No problems found.")); + } else { + // prepare data model + Object[][] model = new Object[messages.size()][3]; + int i = 0; + for (IntegrityMessage message : messages) { + model[i][0] = message.getEntry().getCiteKey(); + model[i][1] = message.getFieldName(); + model[i][2] = message.getMessage(); + i++; + } + + // construct view + JTable table = new JTable(model, + new Object[] {Localization.lang("BibTeX key"), Localization.lang("Field"), + Localization.lang("Message")}); + + table.setAutoCreateRowSorter(true); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + table.setDefaultEditor(Object.class, null); + ListSelectionModel selectionModel = table.getSelectionModel(); + + selectionModel.addListSelectionListener(event -> { + if (!event.getValueIsAdjusting()) { + String citeKey = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][0]; + String fieldName = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][1]; + frame.getCurrentBasePanel().editEntryByKeyAndFocusField(citeKey, fieldName); + } + }); + + table.setRowHeight(Globals.prefs.getInt(JabRefPreferences.MENU_FONT_SIZE) + 2); + + table.getColumnModel().getColumn(0).setPreferredWidth(80); + table.getColumnModel().getColumn(1).setPreferredWidth(30); + table.getColumnModel().getColumn(2).setPreferredWidth(250); + table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + JScrollPane scrollPane = new JScrollPane(table); + String title = Localization.lang("%0 problem(s) found", String.valueOf(messages.size())); + JDialog dialog = new JDialog(frame, title, false); + dialog.add(scrollPane); + dialog.setSize(600, 500); + + // show view + dialog.setVisible(true); + } + } +} diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 55f5d0a9225d..894176d03eb4 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -698,7 +698,7 @@ private String fixKey() throws IOException { } // Finished, now reverse newKey and remove whitespaces: - parserResult.addWarning(Localization.lang("Line %0: Found corrupted BibTeX-key.", + parserResult.addWarning(Localization.lang("Line %0: Found corrupted BibTeX key.", String.valueOf(line))); key = newKey.reverse(); } @@ -706,12 +706,12 @@ private String fixKey() throws IOException { break; case ',': - parserResult.addWarning(Localization.lang("Line %0: Found corrupted BibTeX-key (contains whitespaces).", + parserResult.addWarning(Localization.lang("Line %0: Found corrupted BibTeX key (contains whitespaces).", String.valueOf(line))); break; case '\n': - parserResult.addWarning(Localization.lang("Line %0: Found corrupted BibTeX-key (comma missing).", + parserResult.addWarning(Localization.lang("Line %0: Found corrupted BibTeX key (comma missing).", String.valueOf(line))); break; diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 680960ed8918..3ec74786dfd9 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -897,9 +897,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Fjern_ Forward=Frem Back=Tilbage Sort_the_following_fields_as_numeric_fields=Sorter_følgende_felter_som_numeriske_felter -Line_%0\:_Found_corrupted_BibTeX-key.=Linje_%0\:_Fandt_ødelagt_BibTeX-nøgle. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Linje_%0\:_Fandt_ødelagt_BibTeX-nøgle_(indeholder_blanktegn). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Linje_%0\:_Fandt_ødelagt_BibTeX-nøgle_(manglende_komma). +Line_%0\:_Found_corrupted_BibTeX_key.=Linje_%0\:_Fandt_ødelagt_BibTeX-nøgle. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Linje_%0\:_Fandt_ødelagt_BibTeX-nøgle_(indeholder_blanktegn). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Linje_%0\:_Fandt_ødelagt_BibTeX-nøgle_(manglende_komma). Finished_downloading_full_text_document=Download_af_fuldtekst-dokument_afsluttet Full_text_document_download_failed=Download_af_fuldtekst-dokument_mislykkedes Update_to_current_column_order=Brug_nuværende_kolonnerækkefølge @@ -1674,3 +1674,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 710edadc5f62..0268c6679dc2 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1607,9 +1607,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Markie Forward=Vor Back=Zurück Sort_the_following_fields_as_numeric_fields=Sortiere_folgende_Felder_als_numerische_Felder -Line_%0\:_Found_corrupted_BibTeX-key.=Zeile_%0\:_Beschädigter_BibTeX-Key_gefunden. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Zeile_%0\:_Beschädigter_BibTeX-Key_gefunden_(enthält_Leerzeichen). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Zeile_%0\:_Beschädigter_BibTeX-Key_gefunden_(Komma_fehlt). +Line_%0\:_Found_corrupted_BibTeX_key.=Zeile_%0\:_Beschädigter_BibTeX-Key_gefunden. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Zeile_%0\:_Beschädigter_BibTeX-Key_gefunden_(enthält_Leerzeichen). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Zeile_%0\:_Beschädigter_BibTeX-Key_gefunden_(Komma_fehlt). Finished_downloading_full_text_document=Herunterladen_des_Volltext-Dokuments_abgeschlossen Full_text_document_download_failed=Herunterladen_des_Volltext-Beitrags_fehlgeschlagen Update_to_current_column_order=Aktuelle_Spaltenanordnung_verwenden @@ -2392,3 +2392,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index a30551fc2a0a..f3c59cafb6d4 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1511,9 +1511,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Unmark Forward=Forward Back=Back Sort_the_following_fields_as_numeric_fields=Sort_the_following_fields_as_numeric_fields -Line_%0\:_Found_corrupted_BibTeX-key.=Line_%0\:_Found_corrupted_BibTeX-key. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing). +Line_%0\:_Found_corrupted_BibTeX_key.=Line_%0\:_Found_corrupted_BibTeX_key. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing). Finished_downloading_full_text_document=Finished_downloading_full_text_document Full_text_document_download_failed=Full_text_document_download_failed Update_to_current_column_order=Update_to_current_column_order @@ -2255,3 +2255,6 @@ word=word Show_symmetric_diff=Show_symmetric_diff HTML_encoded_character_found=HTML_encoded_character_found + +BibTeX_key=BibTeX_key +Message=Message diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index cc4162d45cd6..123711646086 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -832,9 +832,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Desmar Forward=Adelante Back=Atrás Sort_the_following_fields_as_numeric_fields=Ordenar_los_siguientes_campos_como_campos_numéricos -Line_%0\:_Found_corrupted_BibTeX-key.=Línea_%0\:_Se_ha_encontrado_una_clave_BibTeX_corrupta. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Línea_%0\:_Se_ha_encontrado_una_clave_BibTeX_corrupta_(contiene_espacios_en_blanco) -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Línea_%0\:_Se_ha_encontrado_clave_BibTeX_corrupta_(falta_coma). +Line_%0\:_Found_corrupted_BibTeX_key.=Línea_%0\:_Se_ha_encontrado_una_clave_BibTeX_corrupta. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Línea_%0\:_Se_ha_encontrado_una_clave_BibTeX_corrupta_(contiene_espacios_en_blanco) +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Línea_%0\:_Se_ha_encontrado_clave_BibTeX_corrupta_(falta_coma). Finished_downloading_full_text_document=Se_ha_finalizado_la_descarga_del_texto_completo_del_documento Full_text_document_download_failed=Falló_la_descarga_del_texto_completo_del_artículo Update_to_current_column_order=Actualizar_al_orden_de_columnas_actual @@ -1575,3 +1575,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 613b25f8d508..7d364330a0f8 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1565,8 +1565,8 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database= Forward= Back= Sort_the_following_fields_as_numeric_fields= -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).= -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).= +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).= +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).= Finished_downloading_full_text_document= Full_text_document_download_failed= Update_to_current_column_order= @@ -2064,7 +2064,7 @@ Journal_abbreviations= Keep_left= Keep_merged_entry_only= Keep_right= -Line_%0\:_Found_corrupted_BibTeX-key.= +Line_%0\:_Found_corrupted_BibTeX_key.= Link_local_file= Listen_for_remote_operation_on_port= Look_and_feel= @@ -2362,3 +2362,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 1ebfe9ee796e..abba6cab4111 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -834,9 +834,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Désé Forward=Suivant Back=Précédent Sort_the_following_fields_as_numeric_fields=Trier_les_champs_suivants_comme_des_champs_numériques -Line_%0\:_Found_corrupted_BibTeX-key.=Ligne_%0_\:_Clef_BibTeX_corrompue_trouvée. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Ligne_%0_\:_Clef_BibTeX_corrompue_trouvée_(contient_des_espaces). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Ligne_%0_\:_Clef_BibTeX_corrompue_trouvée_(virgule_manquante). +Line_%0\:_Found_corrupted_BibTeX_key.=Ligne_%0_\:_Clef_BibTeX_corrompue_trouvée. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Ligne_%0_\:_Clef_BibTeX_corrompue_trouvée_(contient_des_espaces). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Ligne_%0_\:_Clef_BibTeX_corrompue_trouvée_(virgule_manquante). Finished_downloading_full_text_document=Téléchargement_du_document_cité_terminé Full_text_document_download_failed=Echec_du_téléchargement_du_document_cité Update_to_current_column_order=Enregistrer_l'ordre_actuel_des_colonnes @@ -1618,3 +1618,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index aefd0bf9ea69..de68507b942c 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -831,9 +831,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Hilang Forward=Maju Back=Kembali Sort_the_following_fields_as_numeric_fields=Urutkan_bidang_berikut_sepeerti_angka -Line_%0\:_Found_corrupted_BibTeX-key.=Baris_%0\:_Ditemukan_kunci_BibTeX_ada_kesalahan. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Baris_%0\:_Ditemukan_kunci_BibTeX_ada_kesalahan_(mengandung_spasi_kosong). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Baris_%0\:_Ditemukan_kunci_BibTeX_ada_kesalahan_(tidak_ada_koma). +Line_%0\:_Found_corrupted_BibTeX_key.=Baris_%0\:_Ditemukan_kunci_BibTeX_ada_kesalahan. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Baris_%0\:_Ditemukan_kunci_BibTeX_ada_kesalahan_(mengandung_spasi_kosong). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Baris_%0\:_Ditemukan_kunci_BibTeX_ada_kesalahan_(tidak_ada_koma). Finished_downloading_full_text_document=Selesai_muaturun_dokumen_teks_lengkap Full_text_document_download_failed=Gagal_muaturun_artikel_teks_lengkap Update_to_current_column_order=Perbarui_sebuai_urutan_kolom_sekarang @@ -1594,3 +1594,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 070186aa68bc..3c0c924198dc 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -912,9 +912,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Rimuov Forward=Successivo Back=Precedente Sort_the_following_fields_as_numeric_fields=Ordina_i_campi_seguenti_come_campi_numerici -Line_%0\:_Found_corrupted_BibTeX-key.=Riga_%0\:_chiave_BibTeX_corrotta. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Riga_%0\:_chiave_BibTeX_corrotta_(contiene_spazi). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Riga_%0\:_chiave_BibTeX_corrotta_(virgola_mancante). +Line_%0\:_Found_corrupted_BibTeX_key.=Riga_%0\:_chiave_BibTeX_corrotta. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Riga_%0\:_chiave_BibTeX_corrotta_(contiene_spazi). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Riga_%0\:_chiave_BibTeX_corrotta_(virgola_mancante). Finished_downloading_full_text_document=Terminato_il_download_del_documento_citato Full_text_document_download_failed=Fallito_il_download_del_documento_citato Update_to_current_column_order=Salvare_l'ordine_delle_colonne_attuale @@ -1694,3 +1694,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 82aec3cfa1ad..d40c3f57bf29 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1588,9 +1588,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=既存 Forward=進む Back=戻る Sort_the_following_fields_as_numeric_fields=以下のフィールドは数値フィールドとして整序 -Line_%0\:_Found_corrupted_BibTeX-key.=%0行め\:_破損したBibTeX鍵を検出しました。 -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=%0行め\:_破損したBibTeX鍵を発見しました(空白が入っている)。 -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=%0行め\:_破損したBibTeX鍵を発見しました(コンマが欠落)。 +Line_%0\:_Found_corrupted_BibTeX_key.=%0行め\:_破損したBibTeX鍵を検出しました。 +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=%0行め\:_破損したBibTeX鍵を発見しました(空白が入っている)。 +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=%0行め\:_破損したBibTeX鍵を発見しました(コンマが欠落)。 Finished_downloading_full_text_document=文書本体のダウンロードが終了しました Full_text_document_download_failed=論文本体のダウンロードに失敗しました Update_to_current_column_order=現在の列順に更新 @@ -2338,3 +2338,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 108ba96dadc2..bc63d5758fb0 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1594,9 +1594,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database= Forward= Back= Sort_the_following_fields_as_numeric_fields= -Line_%0\:_Found_corrupted_BibTeX-key.= -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).= -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).= +Line_%0\:_Found_corrupted_BibTeX_key.= +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).= +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).= Finished_downloading_full_text_document= Full_text_document_download_failed= Update_to_current_column_order= @@ -2372,3 +2372,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 3a7eee7844ed..8bbf6a47316c 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1793,11 +1793,11 @@ Back=Tilbake Sort_the_following_fields_as_numeric_fields=Sorter_de_f\u00c3\u00b8lgende_feltene_som_tall -Line_%0\:_Found_corrupted_BibTeX-key.=Linje_%0\:_Fant_ugyldig_BibTeX-n\u00b8kkel. +Line_%0\:_Found_corrupted_BibTeX_key.=Linje_%0\:_Fant_ugyldig_BibTeX-n\u00b8kkel. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Linje_%0\:_Fant_ugyldig_BibTeX-n\u00b8kkel_(inneholder_mellomrom). +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Linje_%0\:_Fant_ugyldig_BibTeX-n\u00b8kkel_(inneholder_mellomrom). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Linje_%0\:_Fant_ugyldig_BibTeX-n\u00b8kkel_(manglende_komma). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Linje_%0\:_Fant_ugyldig_BibTeX-n\u00b8kkel_(manglende_komma). Finished_downloading_full_text_document=Fullf\u00b8rte_nedlasting_av_fulltekstdokument @@ -2768,3 +2768,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index dadb6cb947ce..f59a2ae8cac2 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -832,9 +832,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Desmar Forward=Avançar Back=Voltar Sort_the_following_fields_as_numeric_fields=Ordenar_os_seguintes_campos_como_campos_numéricos -Line_%0\:_Found_corrupted_BibTeX-key.=Linha_%0\:_Chave_BibTeX_corrompida_encontrada. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Linha_%0\:_Chave_BibTeX_corrompida_encontrada_(contém_espaços_em_branco). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Linha_%0\:_Chave_BibTeX_corrompida_encontrada_(vírgula_faltando). +Line_%0\:_Found_corrupted_BibTeX_key.=Linha_%0\:_Chave_BibTeX_corrompida_encontrada. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Linha_%0\:_Chave_BibTeX_corrompida_encontrada_(contém_espaços_em_branco). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Linha_%0\:_Chave_BibTeX_corrompida_encontrada_(vírgula_faltando). Finished_downloading_full_text_document=O_download_do_texto_completo_foi_finalizado Full_text_document_download_failed=O_download_do_artigo_completo_falhou Update_to_current_column_order=Atualizar_para_ordenação_de_coluna_atual @@ -1588,3 +1588,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 564d5e193e69..78bb80b4bc43 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1559,9 +1559,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Сня Forward=Вперед Back=Назад Sort_the_following_fields_as_numeric_fields=Сортировать_следующие_поля_как_числовые -Line_%0\:_Found_corrupted_BibTeX-key.=Строка_%0\:_Найден_поврежденный_ключ_BibTeX. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Строка_%0\:_Найден_поврежденный_ключ_BibTeX_(содержит_пробелы) -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Строка_%0\:_Найден_поврежденный_ключ_BibTeX_(пропущена_запятая) +Line_%0\:_Found_corrupted_BibTeX_key.=Строка_%0\:_Найден_поврежденный_ключ_BibTeX. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Строка_%0\:_Найден_поврежденный_ключ_BibTeX_(содержит_пробелы) +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Строка_%0\:_Найден_поврежденный_ключ_BibTeX_(пропущена_запятая) Finished_downloading_full_text_document=Загрузка_цитируемого_документа_завершена Full_text_document_download_failed=Ошибка_загрузки_цитируемой_статьи Update_to_current_column_order=Сохранить_текущий_порядок_столбцов @@ -2339,3 +2339,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 5fdc5f71590d..e4a975b4e8d5 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -649,9 +649,9 @@ Left=Vänster Left_entry=Vänster_post Limit_to_fields=Begränsa_till_fält Limit_to_selected_entries=Begränsa_till_valda_poster -Line_%0\:_Found_corrupted_BibTeX-key.= -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).= -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).= +Line_%0\:_Found_corrupted_BibTeX_key.= +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).= +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).= Link=Länk Link_local_file=Länka_till_lokal_fil Link_to_file_%0=Länka_till_fil_%0 @@ -1532,3 +1532,6 @@ word=ord Show_symmetric_diff=Visa_skillnad_symmetriskt HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index a4c33d130061..4773c292e0cb 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -836,9 +836,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Yeni_g Forward=İleri Back=Geri Sort_the_following_fields_as_numeric_fields=Aşağıdaki_alanları_sayısal_olarak_sırala -Line_%0\:_Found_corrupted_BibTeX-key.=Satır_%0\:_Bozulmuş_BibTeX-anahtarı_bulundu. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Satır_%0\:_Bozulmuş_BibTeX-anahtarı_bulundu_(beyaz_boşluk_içeriyor). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Satır_%0\:_Bozulmuş_BibTeX-anahtarı_bulundu_(virgül_kayıp). +Line_%0\:_Found_corrupted_BibTeX_key.=Satır_%0\:_Bozulmuş_BibTeX-anahtarı_bulundu. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Satır_%0\:_Bozulmuş_BibTeX-anahtarı_bulundu_(beyaz_boşluk_içeriyor). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Satır_%0\:_Bozulmuş_BibTeX-anahtarı_bulundu_(virgül_kayıp). Finished_downloading_full_text_document=Tam_metin_belge_indirme_tamamlandı Full_text_document_download_failed=Tam_metin_makale_indirme_başarısız Update_to_current_column_order=Varolan_sütun_sırasına_güncelle @@ -1606,3 +1606,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index fb5e19a5bcfb..0cbc19a403b0 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1589,9 +1589,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=Khử_ Forward=Tới Back=Lui Sort_the_following_fields_as_numeric_fields=Xếp_thứ_tự_các_trường_sau_như_thể_chúng_là_các_trường_kiểu_số -Line_%0\:_Found_corrupted_BibTeX-key.=Dòng_%0\:_Tìm_thấy_khóa-BibTeX_bị_lỗi. -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=Dòng_%0\:_Tìm_thấy_khóa-BibTeX_bị_lỗi_(chứa_khoảng_trắng). -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=Dòng_%0\:_Tìm_thấy_khóa-BibTeX_bị_lỗi_(thiếu_dấu_phẩy). +Line_%0\:_Found_corrupted_BibTeX_key.=Dòng_%0\:_Tìm_thấy_khóa-BibTeX_bị_lỗi. +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=Dòng_%0\:_Tìm_thấy_khóa-BibTeX_bị_lỗi_(chứa_khoảng_trắng). +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Dòng_%0\:_Tìm_thấy_khóa-BibTeX_bị_lỗi_(thiếu_dấu_phẩy). Finished_downloading_full_text_document=Tải_về_tài_liệu_đầy_đủ_hoàn_tất Full_text_document_download_failed=Việc_tải_về_bài_viết_đầy_đủ_thất_bại Update_to_current_column_order=Cập_nhật_theo_thứ_tự_cột_hiện_tại @@ -2363,3 +2363,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 7135e5cccee7..e68fd555c418 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -894,9 +894,9 @@ Unmark_all_entries_before_importing_new_entries_into_an_existing_database=导入 Forward=前进 Back=后退 Sort_the_following_fields_as_numeric_fields=以数值方式排序下列域 -Line_%0\:_Found_corrupted_BibTeX-key.=第_%0_行\:_发现错误的_BibTeX_键。 -Line_%0\:_Found_corrupted_BibTeX-key_(contains_whitespaces).=第_%0_行\:_发现错误的_BibTeX_键(包含空格)。 -Line_%0\:_Found_corrupted_BibTeX-key_(comma_missing).=第_%0_行\:_发现错误的_BibTeX_键(逗号丢失)。 +Line_%0\:_Found_corrupted_BibTeX_key.=第_%0_行\:_发现错误的_BibTeX_键。 +Line_%0\:_Found_corrupted_BibTeX_key_(contains_whitespaces).=第_%0_行\:_发现错误的_BibTeX_键(包含空格)。 +Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=第_%0_行\:_发现错误的_BibTeX_键(逗号丢失)。 Finished_downloading_full_text_document=完成全文下载 Full_text_document_download_failed=下载全文失败 Update_to_current_column_order=使用当前视图中的列顺序 @@ -1600,3 +1600,6 @@ word= Show_symmetric_diff= HTML_encoded_character_found= + +BibTeX_key= +Message= From e1ff632743977c798da9938f02b30a826d22fb6a Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 1 May 2016 16:29:41 +0200 Subject: [PATCH 007/268] Improve symmetric diff --- .../jabref/gui/mergeentries/MergeEntries.java | 43 +++++++------------ .../gui/mergeentries/MergeEntriesTest.java | 34 +++++++++++++++ 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java index 2a12e4b2cc65..16266ff08147 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java @@ -88,25 +88,16 @@ public class MergeEntries { Localization.lang("Show symmetric diff") + " - " + Localization.lang("word"), Localization.lang("Show symmetric diff") + " - " + Localization.lang("character")}; - - enum DiffStyle { - LATEXDIFF, - SYMMETRIC - } - - private static final String ADDITION_START = ""; private static final String REMOVAL_START = ""; - private static final String CHANGE_ADDITION_START = ""; - private static final String CHANGE_REMOVAL_START = ""; + private static final String CHANGE_START = ""; private static final String TAG_END = ""; private static final String HTML_START = ""; private static final String HTML_END = ""; private static final String BODY_STYLE = "body{font:sans-serif}"; private static final String ADDITION_STYLE = ".add{color:blue;text-decoration:underline}"; private static final String REMOVAL_STYLE = ".del{color:red;text-decoration:line-through;}"; - private static final String CHANGE_ADDITION_STYLE = ".cadd{color:green;text-decoration:underline}"; - private static final String CHANGE_REMOVAL_STYLE = ".cdel{color:green;text-decoration:line-through;}"; + private static final String CHANGE_STYLE = ".change{color:#006400;text-decoration:underline}"; private final Set identicalFields = new HashSet<>(); private final Set differentFields = new HashSet<>(); @@ -385,13 +376,13 @@ private void updateTextPanes(Collection fields) { rightString = generateDiffHighlighting(leftString, rightString, ""); break; case 3: // Symmetric style - word - String tmpLeftString = generateSymmetricHighlighting(rightString, leftString, " "); - rightString = generateSymmetricHighlighting(leftString, rightString, " "); + String tmpLeftString = generateSymmetricHighlighting(leftString, rightString, " "); + rightString = generateSymmetricHighlighting(rightString, leftString, " "); leftString = tmpLeftString; break; - case 4: // Symmetric style - word - tmpLeftString = generateSymmetricHighlighting(rightString, leftString, ""); - rightString = generateSymmetricHighlighting(leftString, rightString, ""); + case 4: // Symmetric style - character + tmpLeftString = generateSymmetricHighlighting(leftString, rightString, ""); + rightString = generateSymmetricHighlighting(rightString, leftString, ""); leftString = tmpLeftString; break; default: // Shouldn't happen @@ -415,8 +406,7 @@ private JTextPane getStyledTextPane() { sheet.addRule(BODY_STYLE); sheet.addRule(ADDITION_STYLE); sheet.addRule(REMOVAL_STYLE); - sheet.addRule(CHANGE_ADDITION_STYLE); - sheet.addRule(CHANGE_REMOVAL_STYLE); + sheet.addRule(CHANGE_STYLE); pane.setEditable(false); return pane; } @@ -463,7 +453,7 @@ public static String generateDiffHighlighting(String baseString, String modified return modifiedString; } - private String generateSymmetricHighlighting(String baseString, String modifiedString, String separator) { + public static String generateSymmetricHighlighting(String baseString, String modifiedString, String separator) { if ((baseString != null) && (modifiedString != null)) { List stringList = new ArrayList<>(Arrays.asList(baseString.split(separator))); List> deltaList = new ArrayList<>(DiffUtils @@ -476,26 +466,25 @@ private String generateSymmetricHighlighting(String baseString, String modifiedS switch (delta.getType()) { case CHANGE: for (String line : lines) { - stringList.set(startPos + offset, (offset == 0 ? CHANGE_REMOVAL_START : "") + line); + stringList.set(startPos + offset, (offset == 0 ? CHANGE_START : "") + line); offset++; } - stringList.set((startPos + offset) - 1, stringList.get((startPos + offset) - 1) + TAG_END - + CHANGE_ADDITION_START + String.join(separator, delta.getRevised().getLines()) + TAG_END); + stringList.set((startPos + offset) - 1, stringList.get((startPos + offset) - 1) + TAG_END); break; case DELETE: - for (offset = 0; offset <= (lines.size() - 1); offset++) { - stringList.set(startPos + offset, ""); + for (String line : lines) { + stringList.set(startPos + offset, (offset == 0 ? ADDITION_START : "") + line); + offset++; } + stringList.set((startPos + offset) - 1, stringList.get((startPos + offset) - 1) + TAG_END); break; case INSERT: - stringList.add(delta.getOriginal().getPosition(), - ADDITION_START + String.join(separator, delta.getRevised().getLines()) + TAG_END); break; default: break; } } - return HTML_START + String.join("", stringList) + HTML_END; + return String.join(separator, stringList); } return modifiedString; } diff --git a/src/test/java/net/sf/jabref/gui/mergeentries/MergeEntriesTest.java b/src/test/java/net/sf/jabref/gui/mergeentries/MergeEntriesTest.java index 709a5220b613..6a315132b53e 100644 --- a/src/test/java/net/sf/jabref/gui/mergeentries/MergeEntriesTest.java +++ b/src/test/java/net/sf/jabref/gui/mergeentries/MergeEntriesTest.java @@ -44,4 +44,38 @@ public void testGenerateDiffHighlightingSingleWordDeleteTextWordDiff() { public void testGenerateDiffHighlightingSingleWordDeleteTextCharacterDiff() { assertEquals("foobar", MergeEntries.generateDiffHighlighting("foobar", "foo", "")); } + + @Test + public void generateSymmetricHighlightingSingleWordAddTextWordDiff() { + assertEquals("foo", + MergeEntries.generateSymmetricHighlighting("foo", "foobar", " ")); + } + + @Test + public void generateSymmetricHighlightingSingleWordAddTextCharacterDiff() { + assertEquals("foo", MergeEntries.generateSymmetricHighlighting("foo", "foobar", "")); + } + + @Test + public void generateSymmetricHighlightingSingleWordDeleteTextWordDiff() { + assertEquals("foobar", + MergeEntries.generateSymmetricHighlighting("foobar", "foo", " ")); + } + + @Test + public void generateSymmetricHighlightingSingleWordDeleteTextCharacterDiff() { + assertEquals("foobar", MergeEntries.generateSymmetricHighlighting("foobar", "foo", "")); + } + + @Test + public void generateSymmetricHighlightingMultipleWordsDeleteTextCharacterDiff() { + assertEquals("foobar and something", + MergeEntries.generateSymmetricHighlighting("foobar and something", "foo and thing", "")); + } + + @Test + public void generateSymmetricHighlightingMultipleWordsDeleteTextWordDiff() { + assertEquals("foo bar and some thing", + MergeEntries.generateSymmetricHighlighting("foo bar and some thing", "foo and thing", " ")); + } } From ee4533dbbf29d853532339579f25b1d04aa0a823 Mon Sep 17 00:00:00 2001 From: Tobias Boceck Date: Fri, 29 Apr 2016 10:44:43 +0200 Subject: [PATCH 008/268] Added option to copy version information in the about dialog --- CHANGELOG.md | 1 + .../actions/CopyVersionToClipboardAction.java | 38 ++++++++++++++ .../net/sf/jabref/gui/help/AboutDialog.java | 52 ++++++++++++++++--- .../net/sf/jabref/logic/util/BuildInfo.java | 7 ++- src/main/resources/l10n/JabRef_da.properties | 3 ++ src/main/resources/l10n/JabRef_de.properties | 2 + src/main/resources/l10n/JabRef_en.properties | 2 + src/main/resources/l10n/JabRef_es.properties | 3 ++ src/main/resources/l10n/JabRef_fa.properties | 3 ++ src/main/resources/l10n/JabRef_fr.properties | 3 ++ src/main/resources/l10n/JabRef_in.properties | 3 ++ src/main/resources/l10n/JabRef_it.properties | 3 ++ src/main/resources/l10n/JabRef_ja.properties | 3 ++ src/main/resources/l10n/JabRef_nl.properties | 3 ++ src/main/resources/l10n/JabRef_no.properties | 3 ++ .../resources/l10n/JabRef_pt_BR.properties | 3 ++ src/main/resources/l10n/JabRef_ru.properties | 3 ++ src/main/resources/l10n/JabRef_sv.properties | 3 ++ src/main/resources/l10n/JabRef_tr.properties | 3 ++ src/main/resources/l10n/JabRef_vi.properties | 3 ++ src/main/resources/l10n/JabRef_zh.properties | 3 ++ 21 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 src/main/java/net/sf/jabref/gui/actions/CopyVersionToClipboardAction.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 36066ee46fb2..8dc57dc6a60b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Implemented [feature request #1294](https://github.com/JabRef/jabref/issues/1294): Added possibility to filter for `*.jstyle` files in OpenOffice/LibreOffice style selection dialog. Open style selection dialog in directory of last selected file - Added integrity check for ISSN - Add LaTeX to Unicode converter as cleanup operation +- Added an option in the about dialog to easily copy the version information of JabRef ### Fixed - Fixed [#473](https://github.com/JabRef/jabref/issues/473): Values in an entry containing symbols like ' are now properly escaped for exporting to the database diff --git a/src/main/java/net/sf/jabref/gui/actions/CopyVersionToClipboardAction.java b/src/main/java/net/sf/jabref/gui/actions/CopyVersionToClipboardAction.java new file mode 100644 index 000000000000..f60c7bc406ce --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/actions/CopyVersionToClipboardAction.java @@ -0,0 +1,38 @@ +/* Copyright (C) 2016 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.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefGUI; +import net.sf.jabref.gui.ClipBoardManager; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.BuildInfo; + +public class CopyVersionToClipboardAction extends AbstractAction { + + @Override + public void actionPerformed(ActionEvent e) { + String info = String.format("JabRef %s%n%s %s %s %nJava %s", Globals.BUILD_INFO.getVersion(), BuildInfo.OS, + BuildInfo.OS_VERSION, BuildInfo.OS_ARCH, BuildInfo.JAVA_VERSION); + new ClipBoardManager().setClipboardContents(info); + JabRefGUI.getMainFrame().output(Localization.lang("Copied version to clipboard")); + } + +} diff --git a/src/main/java/net/sf/jabref/gui/help/AboutDialog.java b/src/main/java/net/sf/jabref/gui/help/AboutDialog.java index cda017523011..8152946b51f0 100644 --- a/src/main/java/net/sf/jabref/gui/help/AboutDialog.java +++ b/src/main/java/net/sf/jabref/gui/help/AboutDialog.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -15,20 +15,29 @@ */ package net.sf.jabref.gui.help; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; import java.awt.Dimension; -import java.awt.GridLayout; import java.util.Objects; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; import javax.swing.JDialog; +import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; +import javax.swing.SwingConstants; +import javax.swing.border.EmptyBorder; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import net.sf.jabref.Globals; import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.actions.CopyVersionToClipboardAction; import net.sf.jabref.logic.l10n.Localization; public class AboutDialog extends JDialog { @@ -39,9 +48,14 @@ public AboutDialog(JabRefFrame bf) { setLocationRelativeTo(bf); JPanel panel = new JPanel(); - panel.setLayout(new GridLayout()); + panel.setLayout(new BorderLayout()); + JPanel headerPanel = new JPanel(); + headerPanel.setLayout(new BorderLayout()); JTextPane textArea = new JTextPane(); + JLabel versionLabel = new JLabel(); + JButton copyVersionButton = new JButton(); + Box spaceHolder = new Box(BoxLayout.X_AXIS); textArea.setEditable(false); textArea.setCursor(null); @@ -54,10 +68,26 @@ public AboutDialog(JabRefFrame bf) { StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); doc.setParagraphAttributes(0, doc.getLength(), center, false); - panel.add(new JScrollPane(textArea)); + panel.add(headerPanel, BorderLayout.NORTH); + JScrollPane textAreaScrollPanel = new JScrollPane(textArea); + textAreaScrollPanel.setBorder(new EmptyBorder(1, 1, 1, 1)); + panel.add(textAreaScrollPanel, BorderLayout.CENTER); - String text = String.format("JabRef %s%n2003-%s%n%s%n%s%n%nDevelopers: %s%n%nAuthors: %s%n%nExternal Libraries: %s%nCode: %s", - Globals.BUILD_INFO.getVersion(), + headerPanel.setBackground(Color.WHITE); + headerPanel.add(spaceHolder, BorderLayout.WEST); + headerPanel.add(versionLabel, BorderLayout.CENTER); + headerPanel.add(copyVersionButton, BorderLayout.EAST); + + String version = String.format("JabRef %s", Globals.BUILD_INFO.getVersion()); + versionLabel.setText(version); + versionLabel.setOpaque(false); + versionLabel.setHorizontalAlignment(SwingConstants.CENTER); + + styleButtonToHyperlink(copyVersionButton); + copyVersionButton.addActionListener(new CopyVersionToClipboardAction()); + spaceHolder.setPreferredSize(copyVersionButton.getPreferredSize()); + + String text = String.format("%n2003-%s%n%s%n%s%n%nDevelopers: %s%n%nAuthors: %s%n%nExternal Libraries: %s%nCode: %s", Globals.BUILD_INFO.getYear(), "http://www.jabref.org", "GNU General Public License v2 or later", @@ -70,4 +100,14 @@ public AboutDialog(JabRefFrame bf) { getContentPane().add(panel); } + + private void styleButtonToHyperlink(JButton copyVersionButton) { + String copy = String.format("%s", + Localization.lang("Copy_version_to_clipboard")); + copyVersionButton.setText(copy); + copyVersionButton.setOpaque(false); + copyVersionButton.setBorder(new EmptyBorder(1, 1, 1, 1)); + copyVersionButton.setFocusable(false); + copyVersionButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } } diff --git a/src/main/java/net/sf/jabref/logic/util/BuildInfo.java b/src/main/java/net/sf/jabref/logic/util/BuildInfo.java index 088176cbeb1f..058c6278b6f0 100644 --- a/src/main/java/net/sf/jabref/logic/util/BuildInfo.java +++ b/src/main/java/net/sf/jabref/logic/util/BuildInfo.java @@ -22,7 +22,12 @@ public class BuildInfo { private static final String UNKOWN_VERSION = "*unknown*"; - + + public final static String OS = System.getProperty("os.name", UNKOWN_VERSION).toLowerCase(); + public final static String OS_VERSION = System.getProperty("os.version", UNKOWN_VERSION).toLowerCase(); + public final static String OS_ARCH = System.getProperty("os.arch", UNKOWN_VERSION).toLowerCase(); + public final static String JAVA_VERSION = System.getProperty("java.version", UNKOWN_VERSION).toLowerCase(); + private final String version; private final String authors; private final String developers; diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index af1a0201c24d..10965248694a 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1680,3 +1680,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index fbd61d647121..acaeb0fff215 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2398,3 +2398,5 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= +Copy_version_to_clipboard=Kopiere_Version_in_die_Zwischenablage +Copied_version_to_clipboard=Version_in_die_Zwischenablage_kopiert diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index dab00c755315..251d6d88235c 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2260,3 +2260,5 @@ incorrect_control_digit=incorrect_control_digit incorrect_format=incorrect_format Expected_"%0"_to_contain_whitespace=Expected_"%0"_to_contain_whitespace Syntax_error_in_regular-expression_pattern=Syntax_error_in_regular-expression_pattern +Copy_version_to_clipboard=Copy_version_to_clipboard +Copied_version_to_clipboard=Copied_version_to_clipboard diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index abec5abcfd3e..eeaee188abf0 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1581,3 +1581,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 8fbec598ebb5..bbf01f8166d0 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2368,3 +2368,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 9e8768aac235..4064e50360ef 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1624,3 +1624,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 31dc39f5150c..0643fd1cd9bf 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1600,3 +1600,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 41f8043cc768..dec53c680d4a 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1700,3 +1700,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index ae8daec936fd..75ed0b1afafd 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2345,3 +2345,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 635aa4c3f5c6..d770ef423058 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2378,3 +2378,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 9fbb3eade61f..8cad5b7637d2 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2774,3 +2774,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 6a2fea13195a..56839c7d3f7e 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1594,3 +1594,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 231afd7cd01c..e0fd33207628 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2345,3 +2345,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index b7e2c780032d..b351a03f2ae0 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1538,3 +1538,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index c51dea0cd38d..353adaf65dbb 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1612,3 +1612,6 @@ incorrect_format=yanlış_biçem Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 5df85b0db259..bf86774bc1b5 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2369,3 +2369,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 20f34a15f5d1..1f2cfeb6a282 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1607,3 +1607,6 @@ incorrect_format= Expected_"%0"_to_contain_whitespace= Syntax_error_in_regular-expression_pattern= + +Copy_version_to_clipboard= +Copied_version_to_clipboard= From b4e8e5ae1792c66a5845ed60e9782e9fa6921217 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 3 May 2016 19:21:27 +0200 Subject: [PATCH 009/268] Hide helpful comments in issue reports (#1346) --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 278826482106..986d0195a057 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ JabRef version on -Hint: If you use a [development version](http://builds.jabref.org/master/), ensure that you use the latest one. + Steps to reproduce: @@ -7,4 +7,4 @@ Steps to reproduce: 2. ... 3. ... -If applicable, excerpt of the bibliography file, screenshot, and excerpt of log (available in the error console) + From e543335e62fc5ecea95e079c84c4477e32034a6a Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Tue, 3 May 2016 21:06:51 +0200 Subject: [PATCH 010/268] Fix NPE on selecting invalid jstyle NPE was raised in Comparator because name was initalized with null instead of Empty string Only store preferences if style is valid --- .../sf/jabref/gui/openoffice/StyleSelectDialog.java | 6 ++++-- .../net/sf/jabref/logic/openoffice/OOBibStyle.java | 4 ++-- .../net/sf/jabref/logic/openoffice/StyleLoader.java | 11 +++++++++-- .../sf/jabref/logic/openoffice/StyleLoaderTest.java | 10 +++++----- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java index e5a547752edf..b5d54ebd06d5 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java @@ -132,8 +132,9 @@ private void init() { addDialog.setDirectoryPath(preferences.getCurrentStyle()); addDialog.setVisible(true); addDialog.getFileName().ifPresent(fileName -> { - loader.addStyle(fileName); - preferences.setCurrentStyle(fileName); + if (loader.addStyleIfValid(fileName)) { + preferences.setCurrentStyle(fileName); + } }); updateStyles(); @@ -310,6 +311,7 @@ public void setVisible(boolean visible) { * settings, and add the styles to the list of styles. */ private void updateStyles() { + table.clearSelection(); styles.getReadWriteLock().writeLock().lock(); styles.clear(); diff --git a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java index ca4fc29d867d..17f35203b301 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java @@ -68,7 +68,7 @@ public class OOBibStyle implements Comparable { public static final String UNDEFINED_CITATION_MARKER = "??"; - private String name; + private String name = ""; private final SortedSet journals = new TreeSet<>(); // Formatter to be run on fields before they are used as part of citation marker: @@ -229,7 +229,7 @@ public Set getJournals() { } private void initialize(InputStream stream) throws IOException { - name = null; + try (Reader reader = new InputStreamReader(stream, encoding)) { readFormatFile(reader); } diff --git a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java index 15ac78d15717..f945b8053aac 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java @@ -64,7 +64,12 @@ public List getStyles() { return result; } - public void addStyle(String filename) { + /** + * Adds the given style to the list of styles + * @param filename The filename of the style + * @return True if the added style is valid, false otherwise + */ + public boolean addStyleIfValid(String filename) { Objects.requireNonNull(filename); try { OOBibStyle newStyle = new OOBibStyle(new File(filename), repository, encoding); @@ -73,6 +78,7 @@ public void addStyle(String filename) { } else if (newStyle.isValid()) { externalStyles.add(newStyle); storeExternalStyles(); + return true; } else { LOGGER.error(String.format("Style with filename %s is invalid", filename)); } @@ -82,6 +88,7 @@ public void addStyle(String filename) { } catch (IOException e) { LOGGER.info("Problem reading external style file " + filename, e); } + return false; } @@ -92,7 +99,7 @@ private void loadExternalStyles() { for (String filename : lists) { try { OOBibStyle style = new OOBibStyle(new File(filename), repository, encoding); - if (style.isValid()) { + if (style.isValid()) { //Problem! externalStyles.add(style); } else { LOGGER.error(String.format("Style with filename %s is invalid", filename)); diff --git a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java index 0b25716fe349..c4c9c27a24bf 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java @@ -85,7 +85,7 @@ public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); - loader.addStyle(filename); + loader.addStyleIfValid(filename); assertEquals(numberOfInternalStyles + 1, loader.getStyles().size()); } @@ -96,7 +96,7 @@ public void testAddInvalidStyleLeadsToNoMoreStyle() { loader = new StyleLoader(preferences, mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); int beforeAdding = loader.getStyles().size(); - loader.addStyle("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky"); + loader.addStyleIfValid("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky"); assertEquals(beforeAdding, loader.getStyles().size()); } @@ -170,8 +170,8 @@ public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException int beforeAdding = loader.getStyles().size(); String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); - loader.addStyle(filename); - loader.addStyle(filename); + loader.addStyleIfValid(filename); + loader.addStyleIfValid(filename); assertEquals(beforeAdding + 1, loader.getStyles().size()); } @@ -179,7 +179,7 @@ public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException public void testAddNullStyleThrowsNPE() { loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); - loader.addStyle(null); + loader.addStyleIfValid(null); fail(); } From fa7c7dae216d2dddecff7c756122d72516f93665 Mon Sep 17 00:00:00 2001 From: Dennis Tschechlov Date: Wed, 4 May 2016 17:56:47 +0200 Subject: [PATCH 011/268] add test for MsBibExporter --- .../net/sf/jabref/exporter/ExportFormat.java | 7 + .../net/sf/jabref/exporter/IExportFormat.java | 15 + .../net/sf/jabref/logic/msbib/MSBibEntry.java | 80 +-- .../sf/jabref/exporter/ExportFormatTest.java | 9 +- .../exporter/MSBibExportFormatTestFiles.java | 86 +++ .../exporter/MsBibExportFormatTest.java | 78 +++ .../exporter/MsBibExportFormatTest1.bib | 44 ++ .../exporter/MsBibExportFormatTest1.xml | 67 ++ .../exporter/MsBibExportFormatTest2.bib | 14 + .../exporter/MsBibExportFormatTest2.xml | 21 + .../exporter/MsBibExportFormatTest3.bib | 14 + .../exporter/MsBibExportFormatTest3.xml | 28 + .../exporter/MsBibExportFormatTest4.bib | 14 + .../exporter/MsBibExportFormatTest4.xml | 20 + .../exporter/MsBibExportFormatTest5.bib | 14 + .../exporter/MsBibExportFormatTest5.xml | 31 + .../exporter/MsBibExportFormatTest6.bib | 13 + .../exporter/MsBibExportFormatTest6.xml | 20 + .../resources/net/sf/jabref/exporter/test.xml | 585 ++++++++++++++++++ 19 files changed, 1080 insertions(+), 80 deletions(-) create mode 100644 src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java create mode 100644 src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.xml create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.xml create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.xml create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.xml create mode 100644 src/test/resources/net/sf/jabref/exporter/test.xml diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormat.java b/src/main/java/net/sf/jabref/exporter/ExportFormat.java index d7784f184d2e..27bcd440bc61 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/ExportFormat.java @@ -23,6 +23,7 @@ import java.io.Reader; import java.net.URL; import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -310,6 +311,12 @@ public void performExport(final BibDatabaseContext databaseContext, final String } + @Override + public void performExport(final BibDatabaseContext databaseContext, Path file, final Charset encoding, + List entries) throws Exception { + performExport(databaseContext, file.getFileName().toString(), encoding, entries); + } + /** * See if there is a name formatter file bundled with this export format. If so, read * all the name formatters so they can be used by the filter layouts. diff --git a/src/main/java/net/sf/jabref/exporter/IExportFormat.java b/src/main/java/net/sf/jabref/exporter/IExportFormat.java index 3109e875f470..98e19f73b676 100644 --- a/src/main/java/net/sf/jabref/exporter/IExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/IExportFormat.java @@ -16,6 +16,7 @@ package net.sf.jabref.exporter; import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.List; import javax.swing.filechooser.FileFilter; @@ -57,4 +58,18 @@ public interface IExportFormat { void performExport(BibDatabaseContext databaseContext, String file, Charset encoding, List entries) throws Exception; + /** + * Perform the Export. + * Gets the path as a java.nio.path instead of a string. + * + * @param databaseContext the database to export from. + * @param file the Path to the file to write to.The path should be an java.nio.Path + * @param encoding The encoding to use. + * @param entries (may be null) A list containing all entries that + * should be exported. If null, all entries will be exported. + * @throws Exception + */ + void performExport(BibDatabaseContext databaseContext, Path file, Charset encoding, List entries) + throws Exception; + } diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java index 8256e7236efb..3f7a0fec0362 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java @@ -15,7 +15,6 @@ */ package net.sf.jabref.logic.msbib; -import java.io.StringWriter; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -24,20 +23,9 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - import net.sf.jabref.importer.fileformat.ImportFormat; -import net.sf.jabref.logic.layout.LayoutFormatter; + import net.sf.jabref.logic.layout.format.RemoveBrackets; -import net.sf.jabref.logic.layout.format.XMLChars; import net.sf.jabref.logic.mods.PageNumbers; import net.sf.jabref.logic.mods.PersonName; import net.sf.jabref.logic.util.strings.StringUtil; @@ -45,11 +33,8 @@ import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.EntryType; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** @@ -72,7 +57,6 @@ * See http://www.ecma-international.org/publications/standards/Ecma-376.htm */ class MSBibEntry { - private static final Log LOGGER = LogFactory.getLog(MSBibEntry.class); private String sourceType = "Misc"; private String bibTexEntry; @@ -165,7 +149,7 @@ class MSBibEntry { // \b(\w+)\s?[,]?\s?(\w+)\s?[,]?\s?(\w+)\b // WORD SPACE , SPACE WORD SPACE , SPACE WORD // tested using http://www.javaregex.com/test.html - private static final Pattern ADDRESS_PATTERN = Pattern.compile("\\b(\\w+)\\s*[,]?\\s*(\\w+)\\s*[,]?\\s*(\\w+)\\b"); + private static final Pattern ADDRESS_PATTERN = Pattern.compile("\\b(\\w+)\\s?[,]?\\s?(\\w+)\\s?[,]?\\s?(\\w+)\\b"); // Allows 20.3-2007|||20/3- 2007 etc. // (\d{1,2})\s?[.,-/]\s?(\d{1,2})\s?[.,-/]\s?(\d{2,4}) @@ -457,9 +441,7 @@ private void populateFromBibtex(BibEntry bibtex) { productionCompany = bibtex.getField(MSBIB + "productioncompany"); } - if (("ElectronicSource".equals(sourceType) - || "Art".equals(sourceType) - || "Misc".equals(sourceType)) + if (("ElectronicSource".equals(sourceType) || "Art".equals(sourceType) || "Misc".equals(sourceType)) && (bibtex.hasField("title"))) { publicationTitle = bibtex.getField("title"); } @@ -552,21 +534,6 @@ private void populateFromBibtex(BibEntry bibtex) { editors = getAuthors(bibtex.getField("editor")); } - boolean FORMATXML = false; - if (FORMATXML) { - title = format(title); - bibTexAbstract = format(bibTexAbstract); - } - } - - private String format(String value) { - if (value == null) { - return null; - } - String result; - LayoutFormatter chars = new XMLChars(); - result = chars.format(value); - return result; } // http://www.microsoft.com/globaldev/reference/lcid-all.mspx @@ -707,18 +674,6 @@ private String getMSBibSourceType(BibEntry bibtex) { return result; } - private Node getDOMrepresentation() { - Node result = null; - try { - DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - - result = getDOMrepresentation(documentBuilder.newDocument()); - } catch (ParserConfigurationException e) { - LOGGER.warn("Could not create DocumentBuilder", e); - } - return result; - } - private void addField(Document document, Element parent, String name, String value) { if (value == null) { return; @@ -752,7 +707,7 @@ private void addAddress(Document document, Element parent, String address) { } Matcher matcher = ADDRESS_PATTERN.matcher(address); - if (matcher.matches() && (matcher.groupCount() > 3)) { + if (matcher.matches() && (matcher.groupCount() >= 3)) { addField(document, parent, "City", matcher.group(1)); addField(document, parent, "StateProvince", matcher.group(2)); addField(document, parent, "CountryRegion", matcher.group(3)); @@ -768,7 +723,7 @@ private void addDate(Document document, Element parent, String date, String extr } Matcher matcher = DATE_PATTERN.matcher(date); - if (matcher.matches() && (matcher.groupCount() > 3)) { + if (matcher.matches() && (matcher.groupCount() >= 3)) { addField(document, parent, "Month" + extra, matcher.group(1)); addField(document, parent, "Day" + extra, matcher.group(2)); addField(document, parent, "Year" + extra, matcher.group(3)); @@ -777,7 +732,6 @@ private void addDate(Document document, Element parent, String date, String extr public Element getDOMrepresentation(Document document) { - Element msbibEntry = document.createElement(B_COLON + "Source"); addField(document, msbibEntry, "SourceType", sourceType); @@ -840,7 +794,7 @@ public Element getDOMrepresentation(Document document) { addDate(document, msbibEntry, dateAccessed, "Accessed"); - /* SM 2010.10 added month export */ + /* SM 2010.10 added month export */ addField(document, msbibEntry, "Month", month); addField(document, msbibEntry, "URL", url); @@ -872,7 +826,7 @@ public Element getDOMrepresentation(Document document) { addField(document, msbibEntry, BIBTEX + "Price", bibTexPrice); addField(document, msbibEntry, BIBTEX + "Size", bibTexSize); - /* SM: 2010.10 end intype, paper support */ + /* SM: 2010.10 end intype, paper support */ addField(document, msbibEntry, BIBTEX + "InType", bibTexInType); addField(document, msbibEntry, BIBTEX + "Paper", bibTexPaper); @@ -1134,24 +1088,4 @@ public BibEntry getBibtexRepresentation() { return entry; } - /* - * render as XML - * - * TODO This is untested. - */ - @Override - public String toString() { - StringWriter result = new StringWriter(); - try { - DOMSource source = new DOMSource(getDOMrepresentation()); - StreamResult streamResult = new StreamResult(result); - Transformer trans = TransformerFactory.newInstance().newTransformer(); - trans.setOutputProperty(OutputKeys.INDENT, "yes"); - trans.transform(source, streamResult); - } catch (TransformerException e) { - LOGGER.warn("Could not build XML representation", e); - } - return result.toString(); - } - } diff --git a/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java b/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java index f855fe1ae9b0..e9666151e02d 100644 --- a/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java +++ b/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java @@ -1,9 +1,8 @@ package net.sf.jabref.exporter; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; import java.nio.charset.Charset; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -58,11 +57,7 @@ public void testExportingEmptyDatabaseYieldsEmptyFile() throws Exception { File tmpFile = testFolder.newFile(); String filename = tmpFile.getCanonicalPath(); exportFormat.performExport(databaseContext, filename, charset, entries); - try (FileInputStream stream = new FileInputStream(tmpFile); - InputStreamReader reader = new InputStreamReader(stream, charset)) { - char[] buffer = new char[512]; - assertEquals(-1, reader.read(buffer)); // Empty file - } + assertEquals(Collections.emptyList(), Files.readAllLines(tmpFile.toPath())); } @Test(expected = NullPointerException.class) diff --git a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java new file mode 100644 index 000000000000..3e3e5287a26f --- /dev/null +++ b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java @@ -0,0 +1,86 @@ +package net.sf.jabref.exporter; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.MetaData; +import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.importer.fileformat.BibtexImporter; +import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.entry.BibEntry; + +import com.google.common.base.Charsets; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(Parameterized.class) +public class MSBibExportFormatTestFiles { + + public BibDatabaseContext databaseContext; + public Charset charset; + public File tempFile; + public MSBibExportFormat msBibExportFormat; + public BibtexImporter testImporter; + + public static final String PATH_TO_FILE = "src/test/resources/net/sf/jabref/exporter/"; + + @Parameter + public String filename; + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + + @Parameters(name = "{0}") + public static Collection fileNames() throws IOException { + try (Stream stream = Files.list(Paths.get(PATH_TO_FILE))) { + return stream.map(n -> n.getFileName().toString()).filter(n -> n.endsWith(".bib")) + .filter(n -> n.startsWith("MsBibExportFormat")).collect(Collectors.toList()); + } + } + + @Before + public void setUp() throws Exception { + Globals.prefs = JabRefPreferences.getInstance(); + databaseContext = new BibDatabaseContext(new BibDatabase(), new MetaData()); + charset = Charsets.UTF_8; + msBibExportFormat = new MSBibExportFormat(); + tempFile = testFolder.newFile(); + testImporter = new BibtexImporter(); + } + + @Test + public final void testPerformExport() throws IOException { + String xmlFileName = filename.replace(".bib", ".xml"); + String tempFilename = tempFile.getCanonicalPath(); + try (InputStream bibIn = MSBibExportFormat.class.getResourceAsStream(filename)) { + List entries = testImporter.importEntries(bibIn, new OutputPrinterToNull()); + assertNotNull(entries); + msBibExportFormat.performExport(databaseContext, tempFile.getPath(), charset, entries); + } + List expected = Files.readAllLines(Paths.get(PATH_TO_FILE + xmlFileName)); + List exported = Files.readAllLines(Paths.get(tempFilename)); + assertEquals(expected, exported); + } +} diff --git a/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java b/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java new file mode 100644 index 000000000000..dbe8178d1cd8 --- /dev/null +++ b/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java @@ -0,0 +1,78 @@ +package net.sf.jabref.exporter; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; + +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.MetaData; +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.entry.BibEntry; + +import com.google.common.base.Charsets; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + + +public class MsBibExportFormatTest { + + public BibDatabaseContext databaseContext; + public Charset charset; + public File tempFile; + public MSBibExportFormat msBibExportFormat; + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + + @Before + public void setUp() throws Exception { + Globals.prefs = JabRefPreferences.getInstance(); + databaseContext = new BibDatabaseContext(new BibDatabase(), new MetaData()); + charset = Charsets.UTF_8; + msBibExportFormat = new MSBibExportFormat(); + tempFile = testFolder.newFile(); + } + + @Test + public final void testPerformExportWithNoEntry() throws IOException { + List entries = Collections.emptyList(); + String tempFileName = tempFile.getCanonicalPath(); + msBibExportFormat.performExport(databaseContext, tempFileName, charset, entries); + assertEquals(Collections.emptyList(), Files.readAllLines(tempFile.toPath())); + } + + @Test + public final void testPerformExportWithTestBib() throws IOException { + try (FileInputStream stream = new FileInputStream("src/test/resources/net/sf/jabref/bibtexFiles/test.bib"); + InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { + ParserResult result = BibtexParser.parse(reader); + BibDatabase database = result.getDatabase(); + String tempFilename = tempFile.getCanonicalPath(); + List entries = database.getEntries(); + assertNotNull(entries); + msBibExportFormat.performExport(databaseContext, tempFile.getPath(), charset, entries); + List expected = Files.readAllLines(Paths.get("src/test/resources/net/sf/jabref/exporter/test.xml")); + List exported = Files.readAllLines(Paths.get(tempFilename)); + Collections.sort(expected); + Collections.sort(exported); + assertEquals(expected, exported); + } + } +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib new file mode 100644 index 000000000000..3d321249f664 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib @@ -0,0 +1,44 @@ +@unpublished{, + author = {Hanns-Jörg Stoß}, + month = {July}, + note = {a Note}, + abstract = {here should stand something about the content}, + address = {Stuttgart Bawue Deutschland}, + affiliation = {aff}, + booktitle = {Turingmaschinen}, + chapter = {3}, + contents = {con}, + copyright = {cop}, + crossref = {cross}, + edition = {10}, + howpublished = {how}, + isbn = {‎978-3-16-148410-0}, + intype = {intype}, + paper = {paper}, + editor = {Alfred}, + sourceType ={Interview}, + institution = {Institution}, + msbib-abbreviatedcasenumber = {abb}, + msbib-accessed = {12.10.2015}, + msbib-broadcaster = {broad}, + msbib-day = {5}, + msbib-casenumber = {case}, + msbib-court = {court}, + msbib-distributor = {dist}, + msbib-medium = {med}, + msbib-numberofvolume = {10}, + msbib-patentnumber = {pat}, + msbib-productioncompany = {produktion}, + msbib-recordingnumber = {record}, + msbib-reporter = {rep}, + msbib-periodical = {peri}, + msbib-shorttitle = {Turing}, + msbib-station = {stat}, + msbib-theater = {th}, + msbib-type = {type}, + organization = {Besondere Turingmaschinen}, + price = {10}, + school = {Gymnasium Unterrieden}, + series = {ser}, + size = {1000} +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.xml new file mode 100644 index 000000000000..ea955c22fb0b --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.xml @@ -0,0 +1,67 @@ + + + +Report +unpublished +Turing +a Note + + + + +Stoß +Hanns-Jörg + + + + + + +Alfred + + + + +10 +10 + ISBN: ‎978-3-16-148410-0 +Stuttgart +Bawue +Deutschland +Turingmaschinen +3 +peri +Turingmaschinen +Gymnasium Unterrieden +Institution +unpublished +12 +10 +2015 +July +produktion +med +record +th +dist +broad +stat +type +pat +court +rep +case +abb +ser +here should stand something about the content +cross +how +aff +con +cop +10 +1000 +intype +paper + + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib new file mode 100644 index 000000000000..ef5214ba7a3f --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib @@ -0,0 +1,14 @@ +@phdthesis{2002, + title = {Agile Entwicklung Web-basierter Systeme}, + year = {2002}, + type = {type}, + number = {3}, + address = {a}, + journal = {Wirtschaftsinformatik}, + keywords = {software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development}, + language = {english}, + pages = {237--248}, + publisher = {Gabler Verlag}, + url = {http://dx.doi.org/10.1007/BF03250842}, + volume = {44}, +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml new file mode 100644 index 000000000000..99b753ce23a7 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml @@ -0,0 +1,21 @@ + + + +Report +phdthesis +2002 +0 +Agile Entwicklung Web-basierter Systeme +2002 + +237-248 +44 +Gabler Verlag +a +Wirtschaftsinformatik +3 +type +http://dx.doi.org/10.1007/BF03250842 +software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development + + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.bib new file mode 100644 index 000000000000..2f1dcea8447b --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.bib @@ -0,0 +1,14 @@ +@manual{raey, + author = {5}, + journal = {Wirtschaftsinformatik}, + keywords = {software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development}, + language = {english}, + lccn = {0937-6429}, + number = {3}, + pages = {237--248}, + publisher = {Gabler Verlag}, + title = {Agile Entwicklung Web-basierter Systeme}, + url = {http://dx.doi.org/10.1007/BF03250842}, + volume = {44}, + year = {2002} +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.xml new file mode 100644 index 000000000000..58086978ba59 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.xml @@ -0,0 +1,28 @@ + + + +Report +manual +raey +0 +Agile Entwicklung Web-basierter Systeme +2002 + + + + +5 + + + + +237-248 +44 + LCCN: 0937-6429 +Gabler Verlag +Wirtschaftsinformatik +3 +http://dx.doi.org/10.1007/BF03250842 +software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development + + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.bib new file mode 100644 index 000000000000..b61f2321776d --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.bib @@ -0,0 +1,14 @@ +@inbook{raey, + issn = {0937-6429}, + journal = {Wirtschaftsinformatik}, + keywords = {software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development}, + language = {english}, + number = {3}, + pages = {237--248}, + publisher = {Gabler Verlag}, + title = {Agile Entwicklung Web-basierter Systeme}, + url = {http://dx.doi.org/10.1007/BF03250842}, + doi = {10.1000/182}, + volume = {44}, + year = {2002} +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml new file mode 100644 index 000000000000..d35b5b92ddc4 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml @@ -0,0 +1,20 @@ + + + +BookSection +inbook +raey +0 +Agile Entwicklung Web-basierter Systeme +2002 + +237-248 +44 + ISSN: 0937-6429 DOI: 10.1000/182 +Gabler Verlag +Wirtschaftsinformatik +3 +http://dx.doi.org/10.1007/BF03250842 +software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development + + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.bib new file mode 100644 index 000000000000..0aa2db3f38a4 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.bib @@ -0,0 +1,14 @@ +@techreport{ + journal = {Wirtschaftsinformatik}, + author = {Sam and jason}, + keywords = {software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development}, + language = {english}, + mrnumber = {0937-6429}, + number = {3}, + pages = {237--248}, + publisher = {Gabler Verlag}, + title = {Agile Entwicklung Web-basierter Systeme}, + url = {http://dx.doi.org/10.1007/BF03250842}, + volume = {44}, + year = {2002} +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.xml new file mode 100644 index 000000000000..dbe3e0a0f25d --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.xml @@ -0,0 +1,31 @@ + + + +Report +techreport +0 +Agile Entwicklung Web-basierter Systeme +2002 + + + + +Sam + + +jason + + + + +237-248 +44 + MRN: 0937-6429 +Gabler Verlag +Wirtschaftsinformatik +3 +Tech. rep. +http://dx.doi.org/10.1007/BF03250842 +software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development + + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.bib new file mode 100644 index 000000000000..4527fc89b684 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.bib @@ -0,0 +1,13 @@ +@mastersthesis{, + journal = {Wirtschaftsinformatik}, + keywords = {software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development}, + language = {english}, + mrnumber = {0937-6429}, + number = {3}, + pages = {237--248}, + publisher = {Gabler Verlag}, + title = {Agile Entwicklung Web-basierter Systeme}, + url = {http://dx.doi.org/10.1007/BF03250842}, + volume = {44}, + year = {2002} +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.xml new file mode 100644 index 000000000000..a096a34ffd8f --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.xml @@ -0,0 +1,20 @@ + + + +Report +mastersthesis +0 +Agile Entwicklung Web-basierter Systeme +2002 + +237-248 +44 + MRN: 0937-6429 +Gabler Verlag +Wirtschaftsinformatik +3 +Master's thesis +http://dx.doi.org/10.1007/BF03250842 +software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development + + diff --git a/src/test/resources/net/sf/jabref/exporter/test.xml b/src/test/resources/net/sf/jabref/exporter/test.xml new file mode 100644 index 000000000000..fd9958930afb --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/test.xml @@ -0,0 +1,585 @@ + + + +ConferenceProceedings +inproceedings +1358810 +Human-in-the-loop: rethinking security in mobile and pervasive systems +2008 + + + + +Kostakos +Vassilis + + + + +3075-3080 + ISBN: 978-1-60558-012-X DOI: http://doi.acm.org/10.1145/1358628.1358810 +ACM +New York, NY, USA +CHI '08: CHI '08 extended abstracts on Human factors in computing systems +CHI '08: CHI '08 extended abstracts on Human factors in computing systems + + +JournalArticle +820136 +Design and usability in security systems: daily life as a context of use? +2002 + + + + +Clear +Tony + + + + +13-14 +34 + ISSN: 0097-8418 DOI: http://doi.acm.org/10.1145/820127.820136 +ACM +New York, NY, USA +SIGCSE Bull. +4 + + +JournalArticle +1373163 +Useful Computer Security +2008 + + + + +Churchill +Elizabeth + + +Nelson +Les + + +Smetters +K. +Diana + + + + +10-12 +12 + ISSN: 1089-7801 DOI: http://dx.doi.org/10.1109/MIC.2008.67 +IEEE Educational Activities Department +Piscataway +NJ +USA +IEEE Internet Computing +3 + + +ConferenceProceedings +inproceedings +00000000 +Are Usability and Security Two Opposite Directions in Computer Systems? +2004 + + + + +Rozinov +Konstantin + + + + + + +JournalArticle +1025014 +Password Memorability and Security: Empirical Results +2004 + + + + +Yan +Jeff + + +Blackwell +Alan + + +Anderson +Ross + + +Grant +Alasdair + + + + +25-31 +2 + ISSN: 1540-7993 DOI: http://dx.doi.org/10.1109/MSP.2004.81 +IEEE Educational Activities Department +Piscataway +NJ +USA +IEEE Security and Privacy +5 + + +JournalArticle +1102917 +The trouble with login: on usability and computer security in ubiquitous computing +2005 + + + + +Bardram +E. + + + + +357-367 +9 + ISSN: 1617-4909 DOI: http://dx.doi.org/10.1007/s00779-005-0347-6 +Springer-Verlag +London +U +K +Personal Ubiquitous Comput. +6 + + +ConferenceProceedings +inproceedings +1137631 +Extending XP practices to support security requirements engineering +2006 + + + + +Bostr\"{o}m +Gustav + + +W\"{a}yrynen +Jaana + + +Bod\'{e}n +Marine + + +Beznosov +Konstantin + + +Kruchten +Philippe + + + + +11-18 + ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137631 +ACM +New York, NY, USA +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems + + +ConferenceProceedings +inproceedings +1233448 +Increasing security and usability of computer systems with graphical passwords +2007 + + + + +Hinds +Cheryl + + +Ekwueme +Chinedu + + + + +529-530 + ISBN: 978-1-59593-629-5 DOI: http://doi.acm.org/10.1145/1233341.1233448 +ACM +New York, NY, USA +ACM-SE 45: Proceedings of the 45th annual southeast regional conference +ACM-SE 45: Proceedings of the 45th annual southeast regional conference + + +JournalArticle +10250999 +Article with complex Authornames +2004 + + + + +von Hippel +Eric + + +Reagle +Joseph M. +Jr., + + +Sherry +F., Jr. +John + + +van den Huevel +Johan A. +Jr., + + + + +25-31 +2 + ISSN: 1540-7993 DOI: http://dx.doi.org/10.1109/MSP.2004.81 +IEEE Educational Activities Department +Piscataway +NJ +USA +IEEE Security and Privacy +5 + + +ConferenceProceedings +inproceedings +1132768 +Security and usability: the case of the user authentication methods +2006 + + + + +Braz +Christina + + +Robert +Jean-Marc + + + + +199-203 + ISBN: 1-59593-350-6 DOI: http://doi.acm.org/10.1145/1132736.1132768 +ACM +New York, NY, USA +IHM '06: Proceedings of the 18th International Conferenceof the Association Francophone d'Interaction Homme-Machine +IHM '06: Proceedings of the 18th International Conferenceof the Association Francophone d'Interaction Homme-Machine + + +ConferenceProceedings +inproceedings +1251435 +Why Johnny can't encrypt: a usability evaluation of PGP 5.0 +1999 + + + + +Whitten +Alma + + +Tygar +D. +J. + + + + +14-14 +USENIX Association +Berkeley +CA +USA +SSYM'99: Proceedings of the 8th conference on USENIX Security Symposium +SSYM'99: Proceedings of the 8th conference on USENIX Security Symposium + + +ConferenceProceedings +inproceedings +1182529 +Question-based authentication using context data +2006 + + + + +Nosseir +Ann + + +Connor +Richard + + +Revie +Crawford + + +Terzis +Sotirios + + + + +429-432 + ISBN: 1-59593-325-5 DOI: http://doi.acm.org/10.1145/1182475.1182529 +ACM +New York, NY, USA +NordiCHI '06: Proceedings of the 4th Nordic conference on Human-computer interaction +NordiCHI '06: Proceedings of the 4th Nordic conference on Human-computer interaction + + +ConferenceProceedings +inproceedings +1137636 +Trust and tamper-proof software delivery +2006 + + + + +Naedele +Martin + + +Koch +E. +Thomas + + + + +51-58 + ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137636 +ACM +New York, NY, USA +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems + + +ConferenceProceedings +inproceedings +1314293 +Randomized radon transforms for biometric authentication via fingerprint hashing +2007 + + + + +Jakubowski +H. +Mariusz + + +Venkatesan +Ramarathnam + + + + +90-94 + ISBN: 978-1-59593-884-8 DOI: http://doi.acm.org/10.1145/1314276.1314293 +ACM +New York, NY, USA +DRM '07: Proceedings of the 2007 ACM workshop on Digital Rights Management +DRM '07: Proceedings of the 2007 ACM workshop on Digital Rights Management + + +ConferenceProceedings +inproceedings +1137628 +Introduction to software engineering for secure systems: SESS06 -- secure by design +2006 + + + + +Bruschi +Danilo + + +Win +De +Bart + + +Monga +Mattia + + + + +1-2 + ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137628 +ACM +New York, NY, USA +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems + + +ConferenceProceedings +inproceedings +1073004 +Two experiences designing for effective security +2005 + + + + +de Paula +Rog\'{e}rio + + +Ding +Xianghua + + +Dourish +Paul + + +Nies +Kari + + +Pillet +Ben + + +Redmiles +David + + +Ren +Jie + + +Rode +Jennifer + + +Filho +Silva +Roberto + + + + +25-34 + ISBN: 1-59593-178-3 DOI: http://doi.acm.org/10.1145/1073001.1073004 +ACM +New York, NY, USA +SOUPS '05: Proceedings of the 2005 symposium on Usable privacy and security +SOUPS '05: Proceedings of the 2005 symposium on Usable privacy and security + + +ConferenceProceedings +inproceedings +1137633 +How secure is AOP and what can we do about it? +2006 + + + + +Win +De +Bart + + +Piessens +Frank + + +Joosen +Wouter + + + + +27-34 + ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137633 +ACM +New York, NY, USA +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems +SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems + + +Book +1098730 +Security and Usability +2005 + + + + +Cranor +Lorrie + + +Garfinkel +Simson + + + + + ISBN: 0596008279 +O'Reilly Media, Inc. + + +ConferenceProceedings +inproceedings +1143122 +Aligning usability and security: a usability study of Polaris +2006 + + + + +DeWitt +J. +Alexander + + +Kuljis +Jasna + + + + +1-7 + ISBN: 1-59593-448-0 DOI: http://doi.acm.org/10.1145/1143120.1143122 +ACM +New York, NY, USA +SOUPS '06: Proceedings of the second symposium on Usable privacy and security +SOUPS '06: Proceedings of the second symposium on Usable privacy and security + + From bdc83359abea7bb7d73ad901962c010145625f72 Mon Sep 17 00:00:00 2001 From: hakova Date: Wed, 4 May 2016 20:38:11 -0500 Subject: [PATCH 012/268] Updated jabref_tr.properties Translated the most recent four entries to Turkish --- src/main/resources/l10n/JabRef_tr.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 353adaf65dbb..ed98752ddde1 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1610,8 +1610,8 @@ OpenOffice/LibreOffice_integration=OpenOffice/LibreOffice_entegrasyonu incorrect_control_digit=yanlış_kontrol_numarası incorrect_format=yanlış_biçem -Expected_"%0"_to_contain_whitespace= -Syntax_error_in_regular-expression_pattern= +Expected_"%0"_to_contain_whitespace="%0"ın_beyazboşluk_içermesi_bekleniyordu +Syntax_error_in_regular-expression_pattern=Düzenli_ifade_düzeninde_sözdizimi_hatası -Copy_version_to_clipboard= -Copied_version_to_clipboard= +Copy_version_to_clipboard=Sürümü_panoya_kopyala +Copied_version_to_clipboard=Sürüm_panoya_kopyalandı From 0e0ad7724cc92482b3704e022980ae37a6c9e6af Mon Sep 17 00:00:00 2001 From: Admir Obralija Date: Fri, 6 May 2016 19:17:51 +0200 Subject: [PATCH 013/268] Fix enabled OpenConsole button when no tabs are opened. --- src/main/java/net/sf/jabref/gui/JabRefFrame.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 2001ef85b9f3..5693a0856c45 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -1596,6 +1596,7 @@ public void updateEnabledState() { if (tabCount == 0) { getBackAction().setEnabled(false); getForwardAction().setEnabled(false); + setEnabled(openAndSavedDatabasesOnlyActions, false); } From 976cd440fd00c0d2b01da4bfe4e7f787c459af86 Mon Sep 17 00:00:00 2001 From: Koji Date: Sat, 7 May 2016 13:15:20 +0900 Subject: [PATCH 014/268] Updating Japanese translations Updated: - Menu_ja.properties - JabRef_ja.properties --- src/main/resources/l10n/JabRef_ja.properties | 451 ++++++++++--------- src/main/resources/l10n/Menu_ja.properties | 6 +- 2 files changed, 229 insertions(+), 228 deletions(-) diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 75ed0b1afafd..ffe4b05c5619 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -406,7 +406,7 @@ Do_not_write_the_following_fields_to_XMP_Metadata\:=以下のフィールドはX Do_you_want_JabRef_to_do_the_following_operations?=JabRefに以下の操作をさせますか? -Down=下げる +Down=下 Download=ダウンロード @@ -1398,7 +1398,7 @@ This_entry_type_cannot_be_removed.=この項目型は解消できません。 This_external_link_is_of_the_type_'%0',_which_is_undefined._What_do_you_want_to_do?=この外部リンクは「%0」型ですが、これは定義されていません。どうしますか? This_group_contains_entries_based_on_manual_assignment._Entries_can_be_assigned_to_this_group_by_selecting_them_then_using_either_drag_and_drop_or_the_context_menu._Entries_can_be_removed_from_this_group_by_selecting_them_then_using_the_context_menu.= -#! このグループは、手動割り当てによる項目を含んでいます。項目を選択して、ドラッグアンドドロップを行うかコンテクストメニューを使うかすれば、このグループに項目を割り当てることができます。項目を選択してコンテクストメニューを使えば、項目を削除することができます。このグループに割り当てた項目はすべて、他と重複しない鍵を持たなくてはなりません。鍵は一意である限り、いつでも変更することができます。 +このグループは、手動割り当てによる項目を含んでいます。項目を選択して、ドラッグアンドドロップを行うかコンテクストメニューを使うかすれば、このグループに項目を割り当てることができます。項目を選択してコンテクストメニューを使えば、項目を削除することができます。 @@ -2122,229 +2122,230 @@ This_search_contains_entries_in_which_any_field_contains_the_regular_expression_ This_search_contains_entries_in_which_any_field_contains_the_term_%0=この検索結果は、フィールドのうちどれかに用語%0が含まれている項目を表示します。 plain_text=平文 -Attention\:_Password_is_stored_in_plain_text\!=警告:パスワードが平文で保管されています! -Please_specify_both_username_and_password=ユーザー名とパスワードの両方を指定してください +Attention\:_Password_is_stored_in_plain_text\!=警告:パスワードは平文で保管されます! +Please_specify_both_username_and_password=ユーザー名とパスワードをともに指定してください Proxy_requires_authentication=プロキシには認証が必要 -Always_reformat_.bib_file_on_save_and_export= -Allow_overwriting_existing_links.= -Do_not_overwrite_existing_links.= +Always_reformat_.bib_file_on_save_and_export=保存・書出の際、つねに.bibファイルを再整形する +Allow_overwriting_existing_links.=既存リンクの上書きを許可する。 +Do_not_overwrite_existing_links.=既存リンクは上書きしない。 Disable_highlight_groups_matching_entries= -New_%0_database= -Export_sorting= -No_entry_found_for_ISBN_%0_at_www.ebook.de= -An_autosave_file_was_found_for_this_database._This_could_indicate_that_JabRef_didn't_shut_down_cleanly_last_time_the_file_was_used.= -Note\:_A_full_text_search_is_currently_not_supported_for_%0= -Unable_to_autodetect_OpenOffice/LibreOffice_installation._Please_choose_the_installation_directory_manually.= -JabRef_no_longer_supports_'ps'_or_'pdf'_fields.
    File_links_are_now_stored_in_the_'file'_field_and_files_are_stored_in_an_external_file_directory.
    To_make_use_of_this_feature,_JabRef_needs_to_upgrade_file_links.

    = -This_database_uses_outdated_file_links.= -Clear_search= -Close_database= -Close_entry_editor= -Decrease_table_font_size= -Entry_editor,_next_entry= -Entry_editor,_next_panel= -Entry_editor,_next_panel_2= -Entry_editor,_previous_entry= -Entry_editor,_previous_panel= -Entry_editor,_previous_panel_2= -Entry_editor,_store_field= -File_list_editor,_move_entry_down= -File_list_editor,_move_entry_up= -Focus_entry_table= -Import_into_current_database= -Import_into_new_database= -Increase_table_font_size= -New_article= -New_book= -New_entry= -New_from_plain_text= -New_inbook= -New_mastersthesis= -New_phdthesis= -New_proceedings= -New_unpublished= -Next_tab= -Preamble_editor,_store_changes= -Previous_tab= -Push_to_application= -Refresh_OpenOffice/LibreOffice= -Resolve_duplicate_BibTeX_keys= -Save_all= -String_dialog,_add_string= -String_dialog,_remove_string= -Switch_preview_layout= -Synchronize_files= -Unabbreviate= -should_contain_a_protocol= -Copy_preview= -Automatically_setting_file_links= -Regenerating_BibTeX_keys_according_to_metadata= -No_meta_data_present_in_bibfile._Cannot_regenerate_BibTeX_keys= -Regenerate_all_keys_for_the_entries_in_a_BibTeX_file= -Show_debug_level_messages= -Default_bibliography_mode= -New_%0_database_created.= -Show_only_preferences_deviating_from_their_default_value= -default= -key= -type= -value= -Show_preferences= -Save_actions= -Enable_save_actions= -Other_fields= -Show_remaining_fields= -link_should_refer_to_a_correct_file_path= -abbreviation_detected= -wrong_entry_type_as_proceedings_has_page_numbers= -Abbreviate_journal_names= -Abbreviating...= -Adding_fetched_entries= -Are_you_sure_you_want_to_remove_the_already_existent_SQL_DBs?= -Display_keywords_appearing_in_ALL_entries= -Display_keywords_appearing_in_ANY_entry= -Fetching_entries_from_Inspire= -None_of_the_selected_entries_have_BibTeX_keys.= -Unabbreviate_journal_names= -Unabbreviating...= -Usage= -Adds_{}_brackets_around_acronyms,_month_names_and_countries_to_preserve_their_case.= -Converts_units_to_LaTeX_formatting.= -Does_nothing.= -Are_you_sure_you_want_to_reset_all_settings_to_default_values?= -Reset_preferences= -Ill-formed_entrytype_comment_in_bib_file= -Clipboard= -Could_not_paste_entry_as_text\:= -Do_you_still_want_to_continue?= -Please_enter_the_desired_name\:= -SQL_Export= -This_action_will_modify_the_following_field(s)_in_at_least_one_entry_each\:= -This_could_cause_undesired_changes_to_your_entries.= -You_have_entered_an_invalid_or_already_existent_DB_name.= -Run_field_formatter\:= -Table_font_size_is_%0= -Move_linked_files_to_default_file_directory_%0= -Internal_style= -Add_style_file= -Are_you_sure_you_want_to_remove_the_style?= -Current_style_is_'%0'= -Remove_style= -Select_one_of_the_available_styles_or_add_a_style_file_from_disk.= -You_must_select_a_valid_style_file.= -Reload= - -Capitalize= -Capitalize_all_words,_but_converts_articles,_prepositions,_and_conjunctions_to_lower_case.= -Capitalize_the_first_word,_changes_other_words_to_lower_case.= -Changes_all_letters_to_lower_case.= -Changes_all_letters_to_upper_case.= -Changes_the_first_letter_of_all_words_to_capital_case_and_the_remaining_letters_to_lower_case.= -Cleans_up_LaTeX_code.= -Converts_HTML_code_to_LaTeX_code.= -Converts_LaTeX_encoding_to_Unicode_characters.= -Converts_Unicode_characters_to_LaTeX_encoding.= -Converts_ordinals_to_LaTeX_superscripts.= -HTML_to_LaTeX= -LaTeX_cleanup= -LaTeX_to_Unicode= -Lower_case= -Minify_list_of_person_names= -Normalize_date= -Normalize_month= -Normalize_month_to_BibTeX_standard_abbreviation.= -Normalize_names_of_persons= -Normalize_page_numbers= -Normalize_pages_to_BibTeX_standard.= -Normalizes_lists_of_persons_to_the_BibTeX_standard.= -Normalizes_the_date_to_ISO_date_format.= -Ordinals_to_LaTeX_superscript= -Protect_terms= -Remove_enclosing_braces= -Removes_braces_encapsulating_the_complete_field_content.= -Sentence_case= -Shortens_lists_of_persons_if_there_are_more_than_2_persons_to_"et_al.".= -Title_case= -Unicode_to_LaTeX= -Units_to_LaTeX= -Upper_case= -Identity= - -Clears_the_field_completely.= -Directory_not_found= -Main_file_directory_not_set\!= - -This_operation_requires_exactly_one_item_to_be_selected.= - -Importing_in_%0_format= - -Female_name= -Female_names= -Male_name= -Male_names= -Mixed_names= -Neuter_name= -Neuter_names= - -Lookup_DOI= -No_DOI_found= - -Audio_CD= -British_patent= -British_patent_request= -Candidate_thesis= -Collaborator= -Column= -Compiler= -Continuator= -Data_CD= -Editor= -European_patent= -European_patent_request= -Founder= -French_patent= -French_patent_request= -German_patent= -German_patent_request= -Line= -Master's_thesis= -Page= -Paragraph= -Patent= -Patent_request= -PhD_thesis= -Redactor= -Research_report= -Reviser= -Section= -Software= -Technical_report= -U.S._patent= -U.S._patent_request= -Verse= - - -change_entries_of_group= -odd_number_of_unescaped_'\#'= -Plain_text= -Show_diff= -character= -word= - -Show_symmetric_diff= - -HTML_encoded_character_found= - -All_external_files= - -OpenOffice/LibreOffice_integration= - -incorrect_control_digit= -incorrect_format= - -Expected_"%0"_to_contain_whitespace= -Syntax_error_in_regular-expression_pattern= - -Copy_version_to_clipboard= -Copied_version_to_clipboard= +New_%0_database=新規%0データベース +Export_sorting=整序法を書き出す +No_entry_found_for_ISBN_%0_at_www.ebook.de=www.ebook.deにISBN_%0に一致する項目は見つかりませんでした +An_autosave_file_was_found_for_this_database._This_could_indicate_that_JabRef_didn't_shut_down_cleanly_last_time_the_file_was_used.=このデータベースの自動保存ファイルが見つかりました。このファイルを最後に使用した際、JabRefが正常に終了しなかった可能性があります。 +Note\:_A_full_text_search_is_currently_not_supported_for_%0=註:%0ではフルテキスト検索はまだサポートされていません +Unable_to_autodetect_OpenOffice/LibreOffice_installation._Please_choose_the_installation_directory_manually.=OpenOffice/LibreOfficeが導入済みであることを自動検出できませんでした。導入先ディレクトリを手動で選択してください。 +JabRef_no_longer_supports_'ps'_or_'pdf'_fields.
    File_links_are_now_stored_in_the_'file'_field_and_files_are_stored_in_an_external_file_directory.
    To_make_use_of_this_feature,_JabRef_needs_to_upgrade_file_links.

    =JabRefは「ps」「pdf」フィールドのサポートを停止しました。
    現在、ファイルリンクは「file」フィールドに保管され、ファイルは外部のファイルディレクトリに保管されます。
    この機能を利用するには、JabRefにファイルリンクを更新させる必要があります。

    +This_database_uses_outdated_file_links.=このデータベースは旧式のファイルリンクを使用しています。 +Clear_search=検索を消去 +Close_database=データベースを閉じる +Close_entry_editor=項目エディタを閉じる +Decrease_table_font_size=表フォント寸法を減少 +Entry_editor,_next_entry=項目エディタ・次項目 +Entry_editor,_next_panel=項目エディタ・次パネル +Entry_editor,_next_panel_2=項目エディタ・次パネル_2 +Entry_editor,_previous_entry=項目エディタ・前項目 +Entry_editor,_previous_panel=項目エディタ・前パネル +Entry_editor,_previous_panel_2=項目エディタ・前パネル_2 +Entry_editor,_store_field=項目エディタ・フィールドを保存 +File_list_editor,_move_entry_down=ファイル一覧エディタ・項目を下に移動 +File_list_editor,_move_entry_up=ファイル一覧エディタ・項目を上に移動 +Focus_entry_table=項目表にフォーカス +Import_into_current_database=現データベースに読み込む +Import_into_new_database=新規データベースに読み込む +Increase_table_font_size=表フォント寸法を増大 +New_article=新規article +New_book=新規book +New_entry=新規項目 +New_from_plain_text=平文から新規 +New_inbook=新規inbook +New_mastersthesis=新規masterthesis +New_phdthesis=新規phdthesis +New_proceedings=新規proceedings +New_unpublished=新規unpublished +Next_tab=次タブ +Preamble_editor,_store_changes=プリアンブルエディタ・変更を保存 +Previous_tab=前タブ +Push_to_application=アプリケーションにプッシュ +Refresh_OpenOffice/LibreOffice=OpenOffice/LibreOfficeを更新 +Resolve_duplicate_BibTeX_keys=重複BibTeX鍵を解消 +Save_all=全て保存 +String_dialog,_add_string=文字列ダイアログ・文字列を追加 +String_dialog,_remove_string=文字列ダイアログ・文字列を削除 +Switch_preview_layout=プレビューレイアウトを切り替え +Synchronize_files=ファイルを同期 +Unabbreviate=非短縮形化 +should_contain_a_protocol=プロトコルを含む必要あり +Copy_preview=プレビューをコピー +Automatically_setting_file_links=ファイルリンクを自動的に設定 +Regenerating_BibTeX_keys_according_to_metadata=メタデータにしたがってBibTeX鍵を再生成 +No_meta_data_present_in_bibfile._Cannot_regenerate_BibTeX_keys=bibファイルにメタデータがありません。BibTeX鍵を再生成することができません +Regenerate_all_keys_for_the_entries_in_a_BibTeX_file=BibTeXファイル中全項目の鍵を再生成 +Show_debug_level_messages=デバッグレベルメッセージを表示 +Default_bibliography_mode=既定の書誌情報モード +New_%0_database_created.=新規に%0個のデータベースが生成されました。 +Show_only_preferences_deviating_from_their_default_value=既定値と異なる設定のみ表示 +default=既定値 +key=鍵 +type=型 +value=値 +Show_preferences=設定を表示 +Save_actions=アクションを保存 +Enable_save_actions=アクションの保存を有効化 +Other_fields=他のフィールド +Show_remaining_fields=その他のフィールドを表示 +link_should_refer_to_a_correct_file_path=リンクは正しいファイルパスを参照しなくてはなりません +abbreviation_detected=短縮形を検出しました +wrong_entry_type_as_proceedings_has_page_numbers=項目型の誤り:proceedingsにページ番号があります +Abbreviate_journal_names=学術誌名を短縮形化 +Abbreviating...=短縮形化中 +Adding_fetched_entries=取得した項目を追加しています +Are_you_sure_you_want_to_remove_the_already_existent_SQL_DBs?=既存のSQLデータベースを本当に削除しますか? +Display_keywords_appearing_in_ALL_entries=全ての項目に現れるキーワードを表示 +Display_keywords_appearing_in_ANY_entry=いずれかの項目に現れるキーワードを表示 +Fetching_entries_from_Inspire=Inspireから項目を取得 +None_of_the_selected_entries_have_BibTeX_keys.=選択した項目のいずれにもBibTeX鍵がありません。 +Unabbreviate_journal_names=学術誌名を非短縮形化 +Unabbreviating...=非短縮形化中... +Usage=使用法 +Adds_{}_brackets_around_acronyms,_month_names_and_countries_to_preserve_their_case.=大文字が維持されるように、略語や月名、国名の前後には{}括弧を付してください。 +Converts_units_to_LaTeX_formatting.=単位をLaTeX形式に変換します。 +Does_nothing.=何もしません。 +Are_you_sure_you_want_to_reset_all_settings_to_default_values?=本当に全ての設定を既定値に戻しますか? +Reset_preferences=設定をリセット +Ill-formed_entrytype_comment_in_bib_file=bibファイル中に誤った書式の項目型コメントがあります +Clipboard=クリップボード +Could_not_paste_entry_as_text\:=項目をテキストとして貼り付けることができませんでした\: +Do_you_still_want_to_continue?=それでも続けますか? +Please_enter_the_desired_name\:=望む名前を入力してください\: +SQL_Export=SQL書き出し +This_action_will_modify_the_following_field(s)_in_at_least_one_entry_each\:=このアクションは、次の各フィールドをそれぞれ少なくとも1項目以上書き換えます\: +This_could_cause_undesired_changes_to_your_entries.=これはあなたの項目に望ましくない変更を加えるおそれがあります。 +You_have_entered_an_invalid_or_already_existent_DB_name.=無効あるいは既存のDB名を入力しました。 +Run_field_formatter\:=フィールド整形子を起動します\: +Table_font_size_is_%0=表フォント寸法は%0です +Move_linked_files_to_default_file_directory_%0=リンクを張られたファイルを既定ファイルディレクトリ%0に移動します +Internal_style=内部スタイル +Add_style_file=スタイルファイルを追加 +Are_you_sure_you_want_to_remove_the_style?=本当にこのスタイルを削除しますか? +Current_style_is_'%0'=現在のスタイルは「%0」です +Remove_style=スタイルを削除 +Select_one_of_the_available_styles_or_add_a_style_file_from_disk.=利用できるスタイルの一つを選択するか、ディスクからスタイルファイルを追加してください。 +You_must_select_a_valid_style_file.=有効なスタイルファイルを選択しなくてはなりません。 +Reload=再読み込み + +Capitalize=語頭大文字 +Capitalize_all_words,_but_converts_articles,_prepositions,_and_conjunctions_to_lower_case.=全単語の語頭を大文字化しますが、冠詞・前置詞・接続詞は小文字に変換します。 +Capitalize_the_first_word,_changes_other_words_to_lower_case.=最初の単語の語頭を大文字化しますが、他の単語は小文字に変換します。 +Changes_all_letters_to_lower_case.=全文字を小文字に変換します。 +Changes_all_letters_to_upper_case.=全文字を大文字に変換します。 +Changes_the_first_letter_of_all_words_to_capital_case_and_the_remaining_letters_to_lower_case.=全単語の最初の文字を大文字に変換し、他の文字を小文字に変換します。 +Cleans_up_LaTeX_code.=LaTeXコードを一掃します。 +Converts_HTML_code_to_LaTeX_code.=HTMLコードをLaTeXコードに変換します。 +Converts_LaTeX_encoding_to_Unicode_characters.=LaTeXエンコーディングをUnicode文字に変換します。 +Converts_Unicode_characters_to_LaTeX_encoding.=Unicode文字をLaTeXエンコーディングに変換します。 +Converts_ordinals_to_LaTeX_superscripts.=序数をLaTeX上付き文字に変換します。 +HTML_to_LaTeX=HTMLからLaTeXへ +LaTeX_cleanup=LaTeX除去 +LaTeX_to_Unicode=LaTeXからUnicodeへ +Lower_case=小文字 +Minify_list_of_person_names=人名一覧の圧縮 +Normalize_date=日付を標準化 +Normalize_month=月を標準化 +Normalize_month_to_BibTeX_standard_abbreviation.=月をBibTeX標準の短縮形に標準化します。 +Normalize_names_of_persons=人名を標準化 +Normalize_page_numbers=ページ番号を標準化 +Normalize_pages_to_BibTeX_standard.=ページをBibTeX標準に標準化します。 +Normalizes_lists_of_persons_to_the_BibTeX_standard.=人名一覧をBibTeX標準に標準化します。 +Normalizes_the_date_to_ISO_date_format.=日付をISO日付書式に標準化します。 +Ordinals_to_LaTeX_superscript=序数をLaTeX上付き文字に +Protect_terms=用語を保護 +Remove_enclosing_braces=包含括弧を除去 +Removes_braces_encapsulating_the_complete_field_content.=フィールド内容全体を包含する括弧を除去します。 +Sentence_case=文の大小文字パターン +Shortens_lists_of_persons_if_there_are_more_than_2_persons_to_"et_al.".=3名以上の人名リストは「et_al.」に短縮する。 +Title_case=タイトルの大小文字パターン +Unicode_to_LaTeX=UnicodeからLaTeXへ +Units_to_LaTeX=単位からLaTeXへ +Upper_case=大文字 +Identity=同一 + +Clears_the_field_completely.=フィールドを完全に消去する。 +Directory_not_found=ディレクトリが検出されませんでした +Main_file_directory_not_set\!=主幹ファイルディレクトリが設定されていません! + +This_operation_requires_exactly_one_item_to_be_selected.=この操作では、1項目のみ選択されている必要があります。 + +Importing_in_%0_format=%0形式で読み込み + +Female_name=女性名 +Female_names=女性名 +Male_name=男性名 +Male_names=男性名 +Mixed_names=男女名 +Neuter_name=中性名 +Neuter_names=中性名 + +Lookup_DOI=DOIを検索 +No_DOI_found=DOIが見つかりませんでした + +Audio_CD=オーディオCD +British_patent=イギリス特許 +British_patent_request=イギリス特許申請 +Candidate_thesis=博士申請論文 +Collaborator=共著者 +Column=列 +Compiler=コンパイラ +Continuator=継承者 + +Data_CD=データCD +Editor=編集者 +European_patent=欧州特許 +European_patent_request=欧州特許申請 +Founder=設立者 +French_patent=フランス特許 +French_patent_request=フランス特許申請 +German_patent=ドイツ特許 +German_patent_request=ドイツ特許申請 +Line=行 +Master's_thesis=修士論文 +Page=ページ +Paragraph=段落 +Patent=特許 +Patent_request=特許申請 +PhD_thesis=博士論文 +Redactor=校閲者 +Research_report=研究レポート +Reviser=改訂者 +Section=節 +Software=ソフトウェア +Technical_report=技術レポート +U.S._patent=米国特許 +U.S._patent_request=米国特許申請 +Verse=詩句 + + +change_entries_of_group=グループ項目を変更 +odd_number_of_unescaped_'\#'=エスケープしていない「\#」の奇数 +Plain_text=平文 +Show_diff=差異を表示 +character=文字 +word=単語 + +Show_symmetric_diff=差異を対照表示 + +HTML_encoded_character_found=HTMLエンコードされた文字が見つかりました + +All_external_files=全外部ファイル + +OpenOffice/LibreOffice_integration=OpenOffice/LibreOfficeの統合 + +incorrect_control_digit=誤った制御数字 +incorrect_format=誤った書式 + +Expected_"%0"_to_contain_whitespace=空白を入れる「%0」が期待されます +Syntax_error_in_regular-expression_pattern=正規表現パターン中の文法エラー + +Copy_version_to_clipboard=バージョンをクリップボードにコピー +Copied_version_to_clipboard=クリップボードにコピーされたバージョン diff --git a/src/main/resources/l10n/Menu_ja.properties b/src/main/resources/l10n/Menu_ja.properties index 8a363c2458a1..3a77d1d752f8 100644 --- a/src/main/resources/l10n/Menu_ja.properties +++ b/src/main/resources/l10n/Menu_ja.properties @@ -29,7 +29,7 @@ Highlight_groups_matching_all_selected_entries=全選択項目に一致するグ Highlight_groups_matching_any_selected_entry=任意の選択項目に一致するグループを着色 # Help -Online_help= +Online_help=オンラインヘルプ Manage_content_selectors=内容選択メニューの管理(&C) Manage_custom_exports=ユーザー書出の管理(&M) Manage_custom_imports=ユーザー読込の管理(&I) @@ -130,8 +130,8 @@ Delete_entry=項目を削除 Switch_to_%0_mode=%0モードに切換 Check_integrity=整合性検査 -Quality=素質 +Quality=品質 New_%0_database=新しい%0データベース -Disable_highlight_groups_matching_entries=選択したグループを解除する一致する項目 +Disable_highlight_groups_matching_entries=項目に一致するグループのハイライトを無効化 From 4f6c4b8f3a0cb9d8d1ef75957b57d7d4c11d14d7 Mon Sep 17 00:00:00 2001 From: Koji Date: Sat, 7 May 2016 13:50:38 +0900 Subject: [PATCH 015/268] JabRef_ja.properties update Removing trailing return after a key --- src/main/resources/l10n/JabRef_ja.properties | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index ffe4b05c5619..08817721fbda 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1397,8 +1397,7 @@ This_entry_type_cannot_be_removed.=この項目型は解消できません。 This_external_link_is_of_the_type_'%0',_which_is_undefined._What_do_you_want_to_do?=この外部リンクは「%0」型ですが、これは定義されていません。どうしますか? -This_group_contains_entries_based_on_manual_assignment._Entries_can_be_assigned_to_this_group_by_selecting_them_then_using_either_drag_and_drop_or_the_context_menu._Entries_can_be_removed_from_this_group_by_selecting_them_then_using_the_context_menu.= -このグループは、手動割り当てによる項目を含んでいます。項目を選択して、ドラッグアンドドロップを行うかコンテクストメニューを使うかすれば、このグループに項目を割り当てることができます。項目を選択してコンテクストメニューを使えば、項目を削除することができます。 +This_group_contains_entries_based_on_manual_assignment._Entries_can_be_assigned_to_this_group_by_selecting_them_then_using_either_drag_and_drop_or_the_context_menu._Entries_can_be_removed_from_this_group_by_selecting_them_then_using_the_context_menu.=このグループは、手動割り当てによる項目を含んでいます。項目を選択して、ドラッグアンドドロップを行うかコンテクストメニューを使うかすれば、このグループに項目を割り当てることができます。項目を選択してコンテクストメニューを使えば、項目を削除することができます。 From 000d065083eacae31b9f2c5943d31a8c1b83095d Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 7 May 2016 14:16:04 +0200 Subject: [PATCH 016/268] Update PDFBox from 1.8.11 to 1.8.12 Release notes: http://www.apache.org/dist/pdfbox/1.8.12/RELEASE-NOTES.txt --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 63cae66fb8e9..09c8d8b2600b 100644 --- a/build.gradle +++ b/build.gradle @@ -68,9 +68,9 @@ dependencies { compile 'org.swinglabs:swingx:1.6.1' // do not update, 1.6.5.1 is broken - compile 'org.apache.pdfbox:pdfbox:1.8.11' - compile 'org.apache.pdfbox:fontbox:1.8.11' - compile 'org.apache.pdfbox:jempbox:1.8.11' + compile 'org.apache.pdfbox:pdfbox:1.8.12' + compile 'org.apache.pdfbox:fontbox:1.8.12' + compile 'org.apache.pdfbox:jempbox:1.8.12' compile 'org.bouncycastle:bcprov-jdk15on:1.54' compile 'commons-cli:commons-cli:1.3.1' From 953f5d6121dc9f4671c2263c2cd26197c3328b02 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 7 May 2016 14:18:11 +0200 Subject: [PATCH 017/268] Add comments on chosen versions --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 09c8d8b2600b..3713b7ac9c2d 100644 --- a/build.gradle +++ b/build.gradle @@ -68,9 +68,12 @@ dependencies { compile 'org.swinglabs:swingx:1.6.1' // do not update, 1.6.5.1 is broken + // update to 2.0.x is not possible - see https://github.com/JabRef/jabref/pull/1096#issuecomment-208857517 compile 'org.apache.pdfbox:pdfbox:1.8.12' compile 'org.apache.pdfbox:fontbox:1.8.12' compile 'org.apache.pdfbox:jempbox:1.8.12' + + // required for reading write-procted PDFs - see https://github.com/JabRef/jabref/pull/942#issuecomment-209252635 compile 'org.bouncycastle:bcprov-jdk15on:1.54' compile 'commons-cli:commons-cli:1.3.1' From b0533bf9fde0a07989fc3883ede38c68a6dedc0e Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 7 May 2016 14:18:39 +0200 Subject: [PATCH 018/268] Update AssertJ Swing from 3.2.0 to 3.3.0 Changelog: http://joel-costigliola.github.io/assertj/assertj-swing-news.html --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3713b7ac9c2d..48e0a27b55df 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,7 @@ dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' testCompile 'com.github.tomakehurst:wiremock:1.58' - testCompile 'org.assertj:assertj-swing-junit:3.2.0' + testCompile 'org.assertj:assertj-swing-junit:3.3.0' } sourceSets { From f9687367e8b9fe67c02ec59169581430e5d87067 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 8 May 2016 16:05:35 +0200 Subject: [PATCH 019/268] Fix #1347 Open URLs does not work with query strings (#1349) --- src/main/java/net/sf/jabref/gui/desktop/os/Windows.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java b/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java index 630cad547975..3fe266e56f05 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java +++ b/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java @@ -19,8 +19,9 @@ public void openFile(String filePath, String fileType) throws IOException { if (type.isPresent() && !type.get().getOpenWithApplication().isEmpty()) { openFileWithApplication(filePath, type.get().getOpenWithApplication()); } else { - //filePath as string, because it could be an URL - Runtime.getRuntime().exec(new String[] {"explorer.exe", filePath}); + // quote String so explorer handles URL query strings correctly + String quotePath = "\"" + filePath +"\""; + Runtime.getRuntime().exec(new String[] {"explorer.exe", quotePath}); } } From fc9da2f83b5fb49103c23389e07b5de30c582e46 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 8 May 2016 18:31:45 +0200 Subject: [PATCH 020/268] Fixes some coverity issues missing super calls Removed unnecessary casts Clone should implement Cloneable Use lamdbdas --- .../sf/jabref/external/push/PushToLyx.java | 1 + .../java/net/sf/jabref/gui/DragDropPane.java | 1 + .../gui/groups/GroupAddRemoveDialog.java | 68 +++++++------------ .../sf/jabref/model/database/EntrySorter.java | 15 +--- .../net/sf/jabref/model/entry/BibEntry.java | 2 +- .../sf/jabref/model/entry/BibtexString.java | 2 +- .../java/net/sf/jabref/sql/DatabaseUtil.java | 17 ++++- .../jabref/sql/exporter/DatabaseExporter.java | 11 +-- .../sf/jabref/logic/groups/TreeNodeTest.java | 9 +-- 9 files changed, 59 insertions(+), 67 deletions(-) diff --git a/src/main/java/net/sf/jabref/external/push/PushToLyx.java b/src/main/java/net/sf/jabref/external/push/PushToLyx.java index abf4b99c8c68..8ee32d18e2f0 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToLyx.java +++ b/src/main/java/net/sf/jabref/external/push/PushToLyx.java @@ -75,6 +75,7 @@ public void operationCompleted(BasePanel panel) { @Override protected void initSettingsPanel() { + super.initSettingsPanel(); settings = new JPanel(); settings.add(new JLabel(Localization.lang("Path to LyX pipe") + ":")); settings.add(path); diff --git a/src/main/java/net/sf/jabref/gui/DragDropPane.java b/src/main/java/net/sf/jabref/gui/DragDropPane.java index 41420da71848..388a29881f73 100644 --- a/src/main/java/net/sf/jabref/gui/DragDropPane.java +++ b/src/main/java/net/sf/jabref/gui/DragDropPane.java @@ -152,6 +152,7 @@ public MarkerPane() { @Override public void paintComponent(Graphics g) { + super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.setComposite(AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.9f)); // Set transparency diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupAddRemoveDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupAddRemoveDialog.java index 4342257d2706..bf11b8e0b247 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupAddRemoveDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupAddRemoveDialog.java @@ -1,3 +1,18 @@ +/* Copyright (C) 20013-2016 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.groups; import java.awt.BorderLayout; @@ -17,8 +32,6 @@ import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; @@ -67,9 +80,9 @@ public void action() throws Throwable { selection = panel.getSelectedEntries(); final JDialog diag = new JDialog(panel.frame(), - (add ? (move ? Localization.lang("Move to group") : - Localization.lang("Add to group")) : - Localization.lang("Remove from group")), true); + (add ? (move ? Localization.lang("Move to group") : Localization.lang("Add to group")) : Localization + .lang("Remove from group")), + true); ok = new JButton(Localization.lang("OK")); JButton cancel = new JButton(Localization.lang("Cancel")); tree = new JTree(new GroupTreeNodeViewModel(groups)); @@ -80,7 +93,10 @@ public void action() throws Throwable { // The scrollbar appears when the preferred size of a component is greater than the size of the viewport. If one hard coded the preferred size, it will never change according to the expansion/collapse. Thus the scrollbar cannot appear accordingly. //tree.setSelectionModel(new VetoableTreeSelectionModel()); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - tree.addTreeSelectionListener(new SelectionListener()); + tree.addTreeSelectionListener(e -> { + GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) e.getNewLeadSelectionPath().getLastPathComponent(); + ok.setEnabled(checkGroupEnable(node)); + }); //STA add expand and collapse all buttons JButton jbExpandAll = new JButton("Expand All"); @@ -153,6 +169,7 @@ private void expandAll(final JTree tree, final TreePath parent, final boolean ex TreePath path = parent.pathByAddingChild(n); expandAll(tree, path, expand); } + } // "expand" / "collapse" occurs from bottom to top: if (expand) { @@ -162,17 +179,6 @@ private void expandAll(final JTree tree, final TreePath parent, final boolean ex } } - - private class SelectionListener implements TreeSelectionListener { - - @Override - public void valueChanged(TreeSelectionEvent e) { - GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) e.getNewLeadSelectionPath().getLastPathComponent(); - ok.setEnabled(checkGroupEnable(node)); - } - } - - private boolean doAddOrRemove() { TreePath path = tree.getSelectionPath(); if (path == null) { @@ -208,35 +214,11 @@ private boolean checkGroupEnable(GroupTreeNodeViewModel node) { } - /* private class VetoableTreeSelectionModel extends DefaultTreeSelectionModel { - - @Override - public void addSelectionPath(TreePath path) { - if (checkPath(path)) - super.addSelectionPath(path); - } - - public void setSelectionPath(TreePath path){ - if (checkPath(path)) - super.setSelectionPath(path); - - } - - private boolean checkPath(TreePath path) { - GroupTreeNode node = (GroupTreeNode)path.getLastPathComponent(); - AbstractGroup group = node.getGroup(); - return (add ? group.supportsAdd() && !group.containsAll(GroupAddRemoveDialog.this.selection) - : group.supportsRemove() && group.containsAny(GroupAddRemoveDialog.this.selection)); - } - } - { - - } */ - class AddRemoveGroupTreeCellRenderer extends GroupTreeCellRenderer { @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) { Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) value; diff --git a/src/main/java/net/sf/jabref/model/database/EntrySorter.java b/src/main/java/net/sf/jabref/model/database/EntrySorter.java index f15bcd101981..d498d8e4eb20 100644 --- a/src/main/java/net/sf/jabref/model/database/EntrySorter.java +++ b/src/main/java/net/sf/jabref/model/database/EntrySorter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -43,17 +43,6 @@ public EntrySorter(List entries, Comparator comp) { private void index() { - /* Old version, from when set was a TreeSet. - - // The boolean "changing" is true in the situation that an entry is about to change, - // and has temporarily been removed from the entry set in this sorter. So, if we index - // now, we will cause exceptions other places because one entry has been left out of - // the indexed array. Simply waiting foth this to change can lead to deadlocks, - // so we have no other choice than to return without indexing. - if (changing) - return; - */ - synchronized (set) { // Resort if necessary: @@ -66,6 +55,8 @@ private void index() { // getValueAt() in EntryTableModel, which *has* to be efficient. int count = set.size(); + + entryArray = new BibEntry[count]; int piv = 0; for (BibEntry entry : set) { diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 0e44958e3d6d..18fb5d1e6775 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -42,7 +42,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -public class BibEntry { +public class BibEntry implements Cloneable { private static final Log LOGGER = LogFactory.getLog(BibEntry.class); public static final String TYPE_HEADER = "entrytype"; diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexString.java b/src/main/java/net/sf/jabref/model/entry/BibtexString.java index ce57ab6cace3..95eb37c3dcdf 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexString.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexString.java @@ -18,7 +18,7 @@ /** * This class models a BibTex String ("@String") */ -public class BibtexString { +public class BibtexString implements Cloneable { /** * Type of a \@String. diff --git a/src/main/java/net/sf/jabref/sql/DatabaseUtil.java b/src/main/java/net/sf/jabref/sql/DatabaseUtil.java index fa8d8a80a47f..ea7622e4642f 100644 --- a/src/main/java/net/sf/jabref/sql/DatabaseUtil.java +++ b/src/main/java/net/sf/jabref/sql/DatabaseUtil.java @@ -1,3 +1,18 @@ +/* Copyright (C) 2003-2016 JabRef contributors. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General public static 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 static License for more details. + + You should have received a copy of the GNU General public static 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.sql; import java.sql.Connection; @@ -41,7 +56,7 @@ public static void removeDB(String dbName, Connection conn, BibDatabaseContext d public static int getDatabaseIDByName(BibDatabaseContext databaseContext, Connection out, String dbName) throws SQLException { String query = "SELECT database_id FROM jabref_database WHERE database_name='" + dbName + "';"; - try (Statement statement = (Statement) ((Connection) out).createStatement(); + try (Statement statement = out.createStatement(); ResultSet rs = statement.executeQuery(query)) { if (rs.next()) { return rs.getInt("database_id"); diff --git a/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java b/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java index 1bf3da705cbc..2d74b4f04bc8 100644 --- a/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java +++ b/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 JabRef contributors. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General public static License as published by the Free Software Foundation; either version 2 of the License, or @@ -85,9 +85,10 @@ public DatabaseExporter(Database database) { * @param databaseContext the database to export * @param entriesToExport The list of the entries to export. * @param out The output (PrintStream or Connection) object to which the DML should be written. + * @throws SQLException */ public void performExport(BibDatabaseContext databaseContext, List entriesToExport, - Connection out, String dbName) throws Exception { + Connection out, String dbName) throws SQLException { SavePreferences savePrefs = SavePreferences.loadForExportFromPreferences(Globals.prefs); List entries = BibDatabaseWriter.getSortedEntries(databaseContext, entriesToExport, savePrefs); @@ -144,7 +145,7 @@ private void populateEntriesTable(final int database_id, List entries, */ private int populateEntryGroupsTable(GroupTreeNode cursor, int parentID, int currentID, Connection connection, - final int database_id) throws SQLException { + final int database_id) { if (cursor == null) { // no groups passed @@ -279,7 +280,7 @@ private int populateGroupsTable(GroupTreeNode cursor, int parentID, int currentI + "');"); // recurse on child nodes (depth-first traversal) - try (Statement statement = ((Connection) out).createStatement(); + try (Statement statement = out.createStatement(); ResultSet rs = statement.executeQuery( "SELECT groups_id FROM groups WHERE label='" + cursor.getGroup().getName() + "' AND database_id='" + database_id + "' AND parent_id='" + parentID + "';")) { @@ -308,7 +309,7 @@ private int populateGroupsTable(GroupTreeNode cursor, int parentID, int currentI private static void populateGroupTypesTable(Connection out) throws SQLException { int quantity = 0; - try (Statement sm = ((Connection) out).createStatement(); + try (Statement sm = out.createStatement(); ResultSet res = sm.executeQuery("SELECT COUNT(*) AS amount FROM group_types")) { res.next(); quantity = res.getInt("amount"); diff --git a/src/test/java/net/sf/jabref/logic/groups/TreeNodeTest.java b/src/test/java/net/sf/jabref/logic/groups/TreeNodeTest.java index 306fd0e1ac28..67e1f33802cf 100644 --- a/src/test/java/net/sf/jabref/logic/groups/TreeNodeTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/TreeNodeTest.java @@ -98,6 +98,7 @@ public TreeNodeMock getNodeAsChild(TreeNodeMock root) { return node; } + @SuppressWarnings("unused") @Test(expected = UnsupportedOperationException.class) public void constructorChecksThatClassImplementsCorrectInterface() { new WrongTreeNodeImplementation(); @@ -612,7 +613,7 @@ public void addChildSomewhereInTreeInvokesChangeEvent() { TreeNodeMock root = new TreeNodeMock(); TreeNodeMock node = getNodeInComplexTree(root); - Consumer subscriber = (Consumer) mock(Consumer.class); + Consumer subscriber = mock(Consumer.class); root.subscribeToDescendantChanged(subscriber); node.addChild(new TreeNodeMock()); @@ -625,7 +626,7 @@ public void moveNodeSomewhereInTreeInvokesChangeEvent() { TreeNodeMock node = getNodeInComplexTree(root); TreeNodeMock oldParent = node.getParent().get(); - Consumer subscriber = (Consumer) mock(Consumer.class); + Consumer subscriber = mock(Consumer.class); root.subscribeToDescendantChanged(subscriber); node.moveTo(root); @@ -639,7 +640,7 @@ public void removeChildSomewhereInTreeInvokesChangeEvent() { TreeNodeMock node = getNodeInComplexTree(root); TreeNodeMock child = node.addChild(new TreeNodeMock()); - Consumer subscriber = (Consumer) mock(Consumer.class); + Consumer subscriber = mock(Consumer.class); root.subscribeToDescendantChanged(subscriber); node.removeChild(child); @@ -652,7 +653,7 @@ public void removeChildIndexSomewhereInTreeInvokesChangeEvent() { TreeNodeMock node = getNodeInComplexTree(root); node.addChild(new TreeNodeMock()); - Consumer subscriber = (Consumer) mock(Consumer.class); + Consumer subscriber = mock(Consumer.class); root.subscribeToDescendantChanged(subscriber); node.removeChild(0); From a851fafdcf0d88e70c1c54a30a955f13a1f48541 Mon Sep 17 00:00:00 2001 From: Admir Obralija Date: Mon, 9 May 2016 14:35:54 +0200 Subject: [PATCH 021/268] AddEventSystem (#1028) Full replacement of the old event handling system using Google Guava EventBus. --- CHANGELOG.md | 1 + .../net/sf/jabref/event/EntryAddedEvent.java | 19 ++++ .../sf/jabref/event/EntryChangedEvent.java | 18 ++++ .../java/net/sf/jabref/event/EntryEvent.java | 23 +++++ .../sf/jabref/event/EntryRemovedEvent.java | 19 ++++ .../sf/jabref/event/FieldChangedEvent.java | 32 +++++++ .../java/net/sf/jabref/gui/BasePanel.java | 57 ++++++------ .../java/net/sf/jabref/gui/PreviewPanel.java | 40 ++++----- .../jabref/gui/entryeditor/EntryEditor.java | 32 ++++--- .../gui/maintable/ListSynchronizer.java | 60 +++++++++---- .../gui/maintable/MainTableDataModel.java | 3 +- .../sf/jabref/model/database/BibDatabase.java | 47 +++++----- .../model/database/DatabaseChangeEvent.java | 50 ----------- .../database/DatabaseChangeListener.java | 23 ----- .../sf/jabref/model/database/EntrySorter.java | 62 +++++++------ .../net/sf/jabref/model/entry/BibEntry.java | 90 ++++++------------- .../SpecialFieldDatabaseChangeListener.java | 31 ++++--- .../SpecialFieldUpdateListener.java | 24 ++--- .../sf/jabref/event/TestEventListener.java | 31 +++++++ .../model/database/BibDatabaseTest.java | 24 +++++ 20 files changed, 384 insertions(+), 302 deletions(-) create mode 100644 src/main/java/net/sf/jabref/event/EntryAddedEvent.java create mode 100644 src/main/java/net/sf/jabref/event/EntryChangedEvent.java create mode 100644 src/main/java/net/sf/jabref/event/EntryEvent.java create mode 100644 src/main/java/net/sf/jabref/event/EntryRemovedEvent.java create mode 100644 src/main/java/net/sf/jabref/event/FieldChangedEvent.java delete mode 100644 src/main/java/net/sf/jabref/model/database/DatabaseChangeEvent.java delete mode 100644 src/main/java/net/sf/jabref/model/database/DatabaseChangeListener.java create mode 100644 src/test/java/net/sf/jabref/event/TestEventListener.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dc57dc6a60b..632bb19892c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Implemented [#672](https://github.com/JabRef/jabref/issues/672): FileList now distributes its space dependent on the width of its columns - Added missing German translations - Swedish is added as a language option (still not a complete translation) +- [#969](https://github.com/JabRef/jabref/issues/969) Adding and replacing old event system mechanisms with Google Guava EventBus. ### Fixed - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file diff --git a/src/main/java/net/sf/jabref/event/EntryAddedEvent.java b/src/main/java/net/sf/jabref/event/EntryAddedEvent.java new file mode 100644 index 000000000000..13e23b637296 --- /dev/null +++ b/src/main/java/net/sf/jabref/event/EntryAddedEvent.java @@ -0,0 +1,19 @@ +package net.sf.jabref.event; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * EntryAddedEvent is fired when a new BibEntry was added + * to the database. + */ + +public class EntryAddedEvent extends EntryEvent { + + /** + * @param bibEntry BibEntry object which has been added. + */ + public EntryAddedEvent(BibEntry bibEntry) { + super(bibEntry); + } + +} diff --git a/src/main/java/net/sf/jabref/event/EntryChangedEvent.java b/src/main/java/net/sf/jabref/event/EntryChangedEvent.java new file mode 100644 index 000000000000..eb1e8ada15af --- /dev/null +++ b/src/main/java/net/sf/jabref/event/EntryChangedEvent.java @@ -0,0 +1,18 @@ +package net.sf.jabref.event; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * EntryChangedEvent is fired when a BibEntry has been changed. + */ + +public class EntryChangedEvent extends EntryEvent { + + /** + * @param bibEntry BibEntry object the changes were applied on. + */ + public EntryChangedEvent(BibEntry bibEntry) { + super(bibEntry); + } + +} diff --git a/src/main/java/net/sf/jabref/event/EntryEvent.java b/src/main/java/net/sf/jabref/event/EntryEvent.java new file mode 100644 index 000000000000..8770ab940f59 --- /dev/null +++ b/src/main/java/net/sf/jabref/event/EntryEvent.java @@ -0,0 +1,23 @@ +package net.sf.jabref.event; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * This abstract class pretends a minimal set of attributes and methods + * which an entry event should have. + */ +public abstract class EntryEvent { + + private final BibEntry bibEntry; + + /** + * @param bibEntry BibEntry object which is involved in this event + */ + public EntryEvent(BibEntry bibEntry) { + this.bibEntry = bibEntry; + } + + public BibEntry getBibEntry() { + return this.bibEntry; + } +} diff --git a/src/main/java/net/sf/jabref/event/EntryRemovedEvent.java b/src/main/java/net/sf/jabref/event/EntryRemovedEvent.java new file mode 100644 index 000000000000..888f8fd24676 --- /dev/null +++ b/src/main/java/net/sf/jabref/event/EntryRemovedEvent.java @@ -0,0 +1,19 @@ +package net.sf.jabref.event; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * RemovedEntryEvent is fired when a BibEntry was removed + * from the database. + */ + +public class EntryRemovedEvent extends EntryEvent { + + /** + * @param bibEntry BibEntry object which has been removed. + */ + public EntryRemovedEvent(BibEntry bibEntry) { + super(bibEntry); + } + +} diff --git a/src/main/java/net/sf/jabref/event/FieldChangedEvent.java b/src/main/java/net/sf/jabref/event/FieldChangedEvent.java new file mode 100644 index 000000000000..c5c302ceefa4 --- /dev/null +++ b/src/main/java/net/sf/jabref/event/FieldChangedEvent.java @@ -0,0 +1,32 @@ +package net.sf.jabref.event; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * FieldChangedEvent is fired when a field of BibEntry has been modified, removed or added. + */ +public class FieldChangedEvent extends EntryChangedEvent { + + private final String fieldName; + private final String newValue; + + /** + * @param bibEntry Affected BibEntry object + * @param fieldName Name of field which has been changed + * @param newValue new field value + */ + public FieldChangedEvent(BibEntry bibEntry, String fieldName, String newValue) { + super(bibEntry); + this.fieldName = fieldName; + this.newValue = newValue; + } + + public String getFieldName() { + return fieldName; + } + + public String getNewValue() { + return newValue; + } + +} diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 6c5f474b4c1e..ed59ef189881 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -60,6 +60,8 @@ import net.sf.jabref.collab.ChangeScanner; import net.sf.jabref.collab.FileUpdateListener; import net.sf.jabref.collab.FileUpdatePanel; +import net.sf.jabref.event.EntryAddedEvent; +import net.sf.jabref.event.EntryChangedEvent; import net.sf.jabref.exporter.BibDatabaseWriter; import net.sf.jabref.exporter.ExportToClipboardAction; import net.sf.jabref.exporter.SaveDatabaseAction; @@ -123,9 +125,6 @@ import net.sf.jabref.logic.util.io.FileBasedLock; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.database.BibDatabase; -import net.sf.jabref.model.database.DatabaseChangeEvent; -import net.sf.jabref.model.database.DatabaseChangeEvent.ChangeType; -import net.sf.jabref.model.database.DatabaseChangeListener; import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; @@ -147,6 +146,7 @@ import net.sf.jabref.sql.exporter.DatabaseExporter; import ca.odell.glazedlists.event.ListEventListener; +import com.google.common.eventbus.Subscribe; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; import org.apache.commons.logging.Log; @@ -241,7 +241,7 @@ public BasePanel(JabRefFrame frame, BibDatabaseContext bibDatabaseContext, Chars File file = bibDatabaseContext.getDatabaseFile(); // ensure that at each addition of a new entry, the entry is added to the groups interface - this.database.addDatabaseChangeListener(new GroupTreeUpdater()); + this.database.registerListener(new GroupTreeListener()); if (file == null) { if (database.hasEntries()) { @@ -1256,13 +1256,12 @@ public SearchBar getSearchBar() { * This listener is used to add a new entry to a group (or a set of groups) in case the Group View is selected and * one or more groups are marked */ - private class GroupTreeUpdater implements DatabaseChangeListener { + private class GroupTreeListener { - @Override - public void databaseChanged(final DatabaseChangeEvent e) { - if ((e.getType() == ChangeType.ADDED_ENTRY) && Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP) - && frame.groupToggle.isSelected()) { - final List entries = Collections.singletonList(e.getEntry()); + @Subscribe + public void listen(EntryAddedEvent addedEntryEvent) { + if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP) && frame.groupToggle.isSelected()) { + final List entries = Collections.singletonList(addedEntryEvent.getBibEntry()); final TreePath[] selection = frame.getGroupSelector().getGroupsTree().getSelectionPaths(); if (selection != null) { // it is possible that the user selected nothing. Therefore, checked for "!= null" @@ -1279,13 +1278,16 @@ public void databaseChanged(final DatabaseChangeEvent e) { * Ensures that the search auto completer is up to date when entries are changed AKA Let the auto completer, if any, * harvest words from the entry */ - private class SearchAutoCompleterUpdater implements DatabaseChangeListener { + private class SearchAutoCompleteListener { - @Override - public void databaseChanged(DatabaseChangeEvent e) { - if ((e.getType() == ChangeType.CHANGED_ENTRY) || (e.getType() == ChangeType.ADDED_ENTRY)) { - searchAutoCompleter.addBibtexEntry(e.getEntry()); - } + @Subscribe + public void listen(EntryAddedEvent addedEntryEvent) { + searchAutoCompleter.addBibtexEntry(addedEntryEvent.getBibEntry()); + } + + @Subscribe + public void listen(EntryChangedEvent entryChangedEvent) { + searchAutoCompleter.addBibtexEntry(entryChangedEvent.getBibEntry()); } } @@ -1293,13 +1295,16 @@ public void databaseChanged(DatabaseChangeEvent e) { * Ensures that auto completers are up to date when entries are changed AKA Let the auto completer, if any, harvest * words from the entry */ - private class AutoCompletersUpdater implements DatabaseChangeListener { + private class AutoCompleteListener { - @Override - public void databaseChanged(DatabaseChangeEvent e) { - if ((e.getType() == ChangeType.CHANGED_ENTRY) || (e.getType() == ChangeType.ADDED_ENTRY)) { - BasePanel.this.autoCompleters.addEntry(e.getEntry()); - } + @Subscribe + public void listen(EntryAddedEvent addedEntryEvent) { + BasePanel.this.autoCompleters.addEntry(addedEntryEvent.getBibEntry()); + } + + @Subscribe + public void listen(EntryChangedEvent entryChangedEvent) { + BasePanel.this.autoCompleters.addEntry(entryChangedEvent.getBibEntry()); } } @@ -1348,8 +1353,8 @@ public void updateTableFont() { } private void createMainTable() { - database.addDatabaseChangeListener(tableModel.getEventList()); - database.addDatabaseChangeListener(SpecialFieldDatabaseChangeListener.getInstance()); + database.registerListener(tableModel.getListSynchronizer()); + database.registerListener(SpecialFieldDatabaseChangeListener.getInstance()); tableFormat = new MainTableFormat(database); tableFormat.updateTableFormat(); @@ -1512,7 +1517,7 @@ public void setupMainPanel() { // Set up name autocompleter for search: instantiateSearchAutoCompleter(); - this.getDatabase().addDatabaseChangeListener(new SearchAutoCompleterUpdater()); + this.getDatabase().registerListener(new SearchAutoCompleteListener()); AutoCompletePreferences autoCompletePreferences = new AutoCompletePreferences(Globals.prefs); // Set up AutoCompleters for this panel: @@ -1520,7 +1525,7 @@ public void setupMainPanel() { autoCompleters = new ContentAutoCompleters(getDatabase(), bibDatabaseContext.getMetaData(), autoCompletePreferences, Globals.journalAbbreviationLoader); // ensure that the autocompleters are in sync with entries - this.getDatabase().addDatabaseChangeListener(new AutoCompletersUpdater()); + this.getDatabase().registerListener(new AutoCompleteListener()); } else { // create empty ContentAutoCompleters() if autoCompletion is deactivated autoCompleters = new ContentAutoCompleters(Globals.journalAbbreviationLoader); diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index 25581ae949db..ab6dfa58859d 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -21,9 +21,6 @@ import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.print.PrinterException; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyVetoException; -import java.beans.VetoableChangeListener; import java.io.IOException; import java.io.StringReader; import java.util.Objects; @@ -53,6 +50,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.exporter.ExportFormats; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.fieldeditors.PreviewPanelTransferHandler; @@ -63,13 +61,15 @@ import net.sf.jabref.logic.search.SearchQueryHighlightListener; import net.sf.jabref.model.entry.BibEntry; +import com.google.common.eventbus.Subscribe; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Displays an BibEntry using the given layout format. */ -public class PreviewPanel extends JPanel implements VetoableChangeListener, SearchQueryHighlightListener, EntryContainer { +public class PreviewPanel extends JPanel + implements SearchQueryHighlightListener, EntryContainer { private static final Log LOGGER = LogFactory.getLog(PreviewPanel.class); @@ -105,7 +105,6 @@ public class PreviewPanel extends JPanel implements VetoableChangeListener, Sear private Optional highlightPattern = Optional.empty(); - /** * @param databaseContext * (may be null) Optionally used to resolve strings and for resolving pdf directories for links. @@ -275,16 +274,28 @@ public void setLayout(Layout layout) { } public void setEntry(BibEntry newEntry) { - if(entry.isPresent() && (entry.get() != newEntry)) { - entry.ifPresent(e -> e.removePropertyChangeListener(this)); - newEntry.addPropertyChangeListener(this); + + if (entry.isPresent() && (entry.get() != newEntry)) { + entry.ifPresent(e -> e.unregisterListener(this)); } + + entry.ifPresent(e -> e.registerListener(this)); + entry = Optional.ofNullable(newEntry); updateLayout(); update(); } + + /** + * Listener for ChangedFieldEvent. + */ + @Subscribe + public void listen(FieldChangedEvent fieldChangedEvent) { + update(); + } + @Override public BibEntry getEntry() { return this.entry.orElse(null); @@ -311,19 +322,6 @@ private void scrollToTop() { SwingUtilities.invokeLater(() -> scrollPane.getVerticalScrollBar().setValue(0)); } - /** - * The PreviewPanel has registered itself as an event listener with the - * currently displayed BibEntry. If the entry changes, an event is - * received here, and we can update the preview immediately. - */ - @Override - public void vetoableChange(PropertyChangeEvent evt) - throws PropertyVetoException { - // TODO updating here is not really necessary isn't it? - // Only if we are visible. - update(); - } - @Override public void highlightPattern(Optional newPattern) { this.highlightPattern = newPattern; diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 61662b3b59b5..250d781be1f3 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -29,8 +29,6 @@ import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.VetoableChangeListener; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; @@ -71,6 +69,7 @@ import net.sf.jabref.bibtex.BibEntryWriter; import net.sf.jabref.bibtex.FieldProperties; import net.sf.jabref.bibtex.InternalBibtexFields; +import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.external.WriteXMPEntryEditorAction; import net.sf.jabref.gui.BasePanel; @@ -114,6 +113,7 @@ import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.specialfields.SpecialFieldUpdateListener; +import com.google.common.eventbus.Subscribe; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -123,11 +123,11 @@ *

    * It hosts the tabs (required, general, optional) and the buttons to the left. *

    - * EntryEditor also registers itself as a VetoableChangeListener, receiving + * EntryEditor also registers itself to the event bus, receiving * events whenever a field of the entry changes, enabling the text fields to * update themselves if the change is made from somewhere else. */ -public class EntryEditor extends JPanel implements VetoableChangeListener, EntryContainer { +public class EntryEditor extends JPanel implements EntryContainer { private static final Log LOGGER = LogFactory.getLog(EntryEditor.class); // A reference to the entry this object works on. @@ -203,14 +203,14 @@ public class EntryEditor extends JPanel implements VetoableChangeListener, Entry private final TabListener tabListener = new TabListener(); - public EntryEditor(JabRefFrame frame, BasePanel panel, BibEntry entry) { this.frame = frame; this.panel = panel; this.entry = entry; - this.entry.addPropertyChangeListener(this); - this.entry.addPropertyChangeListener(SpecialFieldUpdateListener.getInstance()); + entry.registerListener(this); + entry.registerListener(SpecialFieldUpdateListener.getInstance()); + displayedBibEntryType = entry.getType(); helpAction = new HelpAction(HelpFiles.ENTRY_EDITOR, IconTheme.JabRefIcon.HELP.getIcon()); @@ -751,13 +751,13 @@ public synchronized void switchTo(BibEntry switchEntry) { storeCurrentEdit(); // Remove this instance as property listener for the entry: - this.entry.removePropertyChangeListener(this); - - // Register as property listener for the new entry: - switchEntry.addPropertyChangeListener(this); + this.entry.unregisterListener(this); this.entry = switchEntry; + // Register as property listener for the new entry: + this.entry.registerListener(this); + updateAllFields(); validateAllFields(); updateSource(); @@ -923,13 +923,11 @@ public void updateAllContentSelectors() { /** * Update the JTextArea when a field has changed. - * - * @see java.beans.VetoableChangeListener#vetoableChange(java.beans.PropertyChangeEvent) */ - @Override - public void vetoableChange(PropertyChangeEvent e) { - String newValue = e.getNewValue() == null ? "" : e.getNewValue().toString(); - setField(e.getPropertyName(), newValue); + @Subscribe + public void listen(FieldChangedEvent fieldChangedEvent) { + String newValue = fieldChangedEvent.getNewValue() == null ? "" : fieldChangedEvent.getNewValue(); + setField(fieldChangedEvent.getFieldName(), newValue); } public void updateField(final Object sourceObject) { diff --git a/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java b/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java index 85a0ffb80701..1915cfe2cd2d 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java +++ b/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java @@ -15,13 +15,15 @@ */ package net.sf.jabref.gui.maintable; -import net.sf.jabref.model.database.DatabaseChangeEvent; -import net.sf.jabref.model.database.DatabaseChangeListener; +import net.sf.jabref.event.EntryAddedEvent; +import net.sf.jabref.event.EntryChangedEvent; +import net.sf.jabref.event.EntryRemovedEvent; import net.sf.jabref.model.entry.BibEntry; import ca.odell.glazedlists.EventList; +import com.google.common.eventbus.Subscribe; -public class ListSynchronizer implements DatabaseChangeListener { +public class ListSynchronizer { private final EventList list; @@ -29,27 +31,47 @@ public ListSynchronizer(EventList list) { this.list = list; } - @Override - public void databaseChanged(DatabaseChangeEvent e) { - list.getReadWriteLock().writeLock().lock(); + @Subscribe + public void listen(EntryAddedEvent entryAddedEvent) { + lock(); + try { + list.add(entryAddedEvent.getBibEntry()); + } finally { + unlock(); + } + } + + @Subscribe + public void listen(EntryRemovedEvent entryRemovedEvent) { + lock(); + try { + list.remove(entryRemovedEvent.getBibEntry()); + } finally { + unlock(); + } + } + + @Subscribe + public void listen(EntryChangedEvent entryChangedEvent) { + lock(); try { - if (e.getType() == DatabaseChangeEvent.ChangeType.ADDED_ENTRY) { - list.add(e.getEntry()); - } else if (e.getType() == DatabaseChangeEvent.ChangeType.REMOVED_ENTRY) { - list.remove(e.getEntry()); - } else if (e.getType() == DatabaseChangeEvent.ChangeType.CHANGED_ENTRY) { - int index = list.indexOf(e.getEntry()); - if (index != -1) { - // SpecialFieldUtils.syncSpecialFieldsFromKeywords update an entry during - // DatabaseChangeEvent.ADDED_ENTRY - // thus, - list.set(index, e.getEntry()); - } + int index = list.indexOf(entryChangedEvent.getBibEntry()); + if (index != -1) { + // SpecialFieldUtils.syncSpecialFieldsFromKeywords update an entry during + // DatabaseChangeEvent.ADDED_ENTRY + // thus, + list.set(index, entryChangedEvent.getBibEntry()); } } finally { - list.getReadWriteLock().writeLock().unlock(); + unlock(); } + } + private void lock() { + list.getReadWriteLock().writeLock().lock(); } + private void unlock() { + list.getReadWriteLock().writeLock().unlock(); + } } diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableDataModel.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableDataModel.java index b2f676c429b9..39b364ce7cc0 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableDataModel.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableDataModel.java @@ -12,7 +12,6 @@ import net.sf.jabref.gui.search.matchers.EverythingMatcher; import net.sf.jabref.gui.search.matchers.SearchMatcher; import net.sf.jabref.gui.util.comparator.IsMarkedComparator; -import net.sf.jabref.model.database.DatabaseChangeListener; import net.sf.jabref.model.entry.BibEntry; import ca.odell.glazedlists.BasicEventList; @@ -137,7 +136,7 @@ DisplayOption getGroupingState() { return filterAndSortingState.groupingState; } - public DatabaseChangeListener getEventList() { + public ListSynchronizer getListSynchronizer() { return this.listSynchronizer; } diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index f5431a3eeead..fe04161dbba5 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -42,11 +42,14 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; +import net.sf.jabref.event.EntryAddedEvent; +import net.sf.jabref.event.EntryRemovedEvent; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.EntryUtil; import net.sf.jabref.model.entry.MonthUtil; +import com.google.common.eventbus.EventBus; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -83,10 +86,7 @@ public class BibDatabase { */ private boolean followCrossrefs = true; - /** - * Behavior - */ - private final Set changeListeners = new HashSet<>(); + private final EventBus eventBus = new EventBus(); /** * Returns the number of entries. @@ -108,7 +108,7 @@ public boolean hasEntries() { */ public synchronized EntrySorter getSorter(Comparator comp) { EntrySorter sorter = new EntrySorter(entries, comp); - addDatabaseChangeListener(sorter); + eventBus.register(sorter); return sorter; } @@ -184,7 +184,7 @@ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionExcep internalIDs.add(id); entries.add(entry); - fireDatabaseChanged(new DatabaseChangeEvent(this, DatabaseChangeEvent.ChangeType.ADDED_ENTRY, entry)); + eventBus.post(new EntryAddedEvent(entry)); return duplicationChecker.checkForDuplicateKeyAndAdd(null, entry.getCiteKey()); } @@ -199,7 +199,7 @@ public synchronized void removeEntry(BibEntry toBeDeleted) { if (anyRemoved) { internalIDs.remove(toBeDeleted.getId()); duplicationChecker.removeKeyFromSet(toBeDeleted.getCiteKey()); - fireDatabaseChanged(new DatabaseChangeEvent(this, DatabaseChangeEvent.ChangeType.REMOVED_ENTRY, toBeDeleted)); + eventBus.post(new EntryRemovedEvent(toBeDeleted)); } } @@ -479,22 +479,6 @@ private String resolveContent(String result, Set usedIds) { return res; } - - - private void fireDatabaseChanged(DatabaseChangeEvent e) { - for (DatabaseChangeListener tmpListener : changeListeners) { - tmpListener.databaseChanged(e); - } - } - - public void addDatabaseChangeListener(DatabaseChangeListener l) { - changeListeners.add(l); - } - - public void removeDatabaseChangeListener(DatabaseChangeListener l) { - changeListeners.remove(l); - } - /** * Returns the text stored in the given field of the given bibtex entry * which belongs to the given database. @@ -562,4 +546,21 @@ public void setEpilog(String epilog) { public String getEpilog() { return epilog; } + + /** + * Registers an listener object (subscriber) to the internal event bus. + * All subscribers should contain at least one @Subscribe annotated + * method accepting one of the following event types: + * + * - {@link EntryAddedEvent} + * - {@link EntryChangedEvent} + * - {@link EntryRemovedEvent} + * + * or another {@link EntryEvent} extending type. + * + * @param object Listener (subscriber) + */ + public void registerListener(Object object) { + this.eventBus.register(object); + } } diff --git a/src/main/java/net/sf/jabref/model/database/DatabaseChangeEvent.java b/src/main/java/net/sf/jabref/model/database/DatabaseChangeEvent.java deleted file mode 100644 index 1f8edbdbac4d..000000000000 --- a/src/main/java/net/sf/jabref/model/database/DatabaseChangeEvent.java +++ /dev/null @@ -1,50 +0,0 @@ -/* 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.model.database; - -import net.sf.jabref.model.entry.BibEntry; - -public class DatabaseChangeEvent { - - public enum ChangeType { - ADDED_ENTRY, REMOVED_ENTRY, CHANGED_ENTRY, CHANGING_ENTRY - } - - - private final BibEntry entry; - private final ChangeType type; - private final BibDatabase source; - - - public DatabaseChangeEvent(BibDatabase source, ChangeType type, - BibEntry entry) { - this.source = source; - this.type = type; - this.entry = entry; - } - - public BibDatabase getSource() { - return source; - } - - public BibEntry getEntry() { - return entry; - } - - public ChangeType getType() { - return type; - } -} diff --git a/src/main/java/net/sf/jabref/model/database/DatabaseChangeListener.java b/src/main/java/net/sf/jabref/model/database/DatabaseChangeListener.java deleted file mode 100644 index 8612573d3448..000000000000 --- a/src/main/java/net/sf/jabref/model/database/DatabaseChangeListener.java +++ /dev/null @@ -1,23 +0,0 @@ -/* 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.model.database; - -@FunctionalInterface -public interface DatabaseChangeListener { - - void databaseChanged(DatabaseChangeEvent e); - -} diff --git a/src/main/java/net/sf/jabref/model/database/EntrySorter.java b/src/main/java/net/sf/jabref/model/database/EntrySorter.java index d498d8e4eb20..e88118fe1d8e 100644 --- a/src/main/java/net/sf/jabref/model/database/EntrySorter.java +++ b/src/main/java/net/sf/jabref/model/database/EntrySorter.java @@ -19,12 +19,16 @@ import java.util.Comparator; import java.util.List; +import net.sf.jabref.event.EntryAddedEvent; +import net.sf.jabref.event.EntryChangedEvent; +import net.sf.jabref.event.EntryRemovedEvent; import net.sf.jabref.model.entry.BibEntry; +import com.google.common.eventbus.Subscribe; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -public class EntrySorter implements DatabaseChangeListener { +public class EntrySorter { private static final Log LOGGER = LogFactory.getLog(EntrySorter.class); @@ -82,35 +86,37 @@ public int getEntryCount() { } } - @Override - public void databaseChanged(DatabaseChangeEvent e) { + @Subscribe + public void listen(EntryAddedEvent EntryAddedEvent) { synchronized (set) { - int pos; - switch (e.getType()) { - case ADDED_ENTRY: - pos = -Collections.binarySearch(set, e.getEntry(), comp) - 1; - LOGGER.debug("Insert position = " + pos); - if (pos >= 0) { - set.add(pos, e.getEntry()); - } else { - set.add(0, e.getEntry()); - } - break; - case REMOVED_ENTRY: - set.remove(e.getEntry()); - changed = true; - break; - case CHANGED_ENTRY: - pos = Collections.binarySearch(set, e.getEntry(), comp); - int posOld = set.indexOf(e.getEntry()); - if (pos < 0) { - set.remove(posOld); - set.add(-posOld - 1, e.getEntry()); - } - break; - default: - break; + int pos = -Collections.binarySearch(set, EntryAddedEvent.getBibEntry(), comp) - 1; + LOGGER.debug("Insert position = " + pos); + if (pos >= 0) { + set.add(pos, EntryAddedEvent.getBibEntry()); + } else { + set.add(0, EntryAddedEvent.getBibEntry()); } } } + + @Subscribe + public void listen(EntryRemovedEvent entryRemovedEvent) { + synchronized (set) { + set.remove(entryRemovedEvent.getBibEntry()); + changed = true; + } + } + + @Subscribe + public void listen(EntryChangedEvent entryChangedEvent) { + synchronized (set) { + int pos = Collections.binarySearch(set, entryChangedEvent.getBibEntry(), comp); + int posOld = set.indexOf(entryChangedEvent.getBibEntry()); + if (pos < 0) { + set.remove(posOld); + set.add(-posOld - 1, entryChangedEvent.getBibEntry()); + } + } + } + } diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 18fb5d1e6775..0bca1fcd8381 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -15,10 +15,6 @@ */ package net.sf.jabref.model.entry; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyVetoException; -import java.beans.VetoableChangeListener; -import java.beans.VetoableChangeSupport; import java.text.DateFormat; import java.text.FieldPosition; import java.text.ParseException; @@ -36,9 +32,11 @@ import java.util.Set; import java.util.TreeSet; +import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.model.database.BibDatabase; import com.google.common.base.Strings; +import com.google.common.eventbus.EventBus; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -54,8 +52,6 @@ public class BibEntry implements Cloneable { private String type; private Map fields = new HashMap<>(); - private final VetoableChangeSupport changeSupport = new VetoableChangeSupport(this); - // Search and grouping status is stored in boolean fields for quick reference: private boolean searchHit; private boolean groupHit; @@ -70,9 +66,13 @@ public class BibEntry implements Cloneable { private boolean changed; + private final EventBus eventBus = new EventBus(); + + /** * Constructs a new BibEntry. The internal ID is set to IdGenerator.next() */ + public BibEntry() { this(IdGenerator.next()); } @@ -108,12 +108,7 @@ public BibEntry(String id, String type) { public void setId(String id) { Objects.requireNonNull(id, "Every BibEntry must have an ID"); - try { - firePropertyChangedEvent(BibEntry.ID_FIELD, this.id, id); - } catch (PropertyVetoException pv) { - throw new IllegalStateException("Couldn't change ID: " + pv); - } - + eventBus.post(new FieldChangedEvent(this, BibEntry.ID_FIELD, id)); this.id = id; changed = true; } @@ -167,18 +162,12 @@ public void setType(String type) { newType = type; } - String oldType = this.type; - - try { - // We set the type before throwing the changeEvent, to enable - // the change listener to access the new value if the change - // sets off a change in database sorting etc. - this.type = newType.toLowerCase(Locale.ENGLISH); - changed = true; - firePropertyChangedEvent(TYPE_HEADER, oldType, newType); - } catch (PropertyVetoException pve) { - LOGGER.warn(pve); - } + // We set the type before throwing the changeEvent, to enable + // the change listener to access the new value if the change + // sets off a change in database sorting etc. + this.type = newType.toLowerCase(Locale.ENGLISH); + changed = true; + eventBus.post(new FieldChangedEvent(this, TYPE_HEADER, newType)); } /** @@ -365,19 +354,8 @@ public void setField(String name, String value) { changed = true; - String oldValue = fields.get(fieldName); - try { - // We set the field before throwing the changeEvent, to enable - // the change listener to access the new value if the change - // sets off a change in database sorting etc. - fields.put(fieldName, value); - firePropertyChangedEvent(fieldName, oldValue, value); - } catch (PropertyVetoException pve) { - // Since we have already made the change, we must undo it since - // the change was rejected: - fields.put(fieldName, oldValue); - throw new IllegalArgumentException("Change rejected: " + pve); - } + fields.put(fieldName, value); + eventBus.post(new FieldChangedEvent(this, fieldName, value)); } /** @@ -394,14 +372,8 @@ public void clearField(String name) { if (BibEntry.ID_FIELD.equals(fieldName)) { throw new IllegalArgumentException("The field name '" + name + "' is reserved"); } - Object oldValue = fields.get(fieldName); fields.remove(fieldName); - try { - firePropertyChangedEvent(fieldName, oldValue, null); - } catch (PropertyVetoException pve) { - throw new IllegalArgumentException("Change rejected: " + pve); - } - + eventBus.post(new FieldChangedEvent(this, fieldName, null)); } /** @@ -447,27 +419,6 @@ private boolean atLeastOnePresent(String[] fieldsToCheck, BibDatabase database) return false; } - private void firePropertyChangedEvent(String fieldName, Object oldValue, Object newValue) - throws PropertyVetoException { - changeSupport.fireVetoableChange(new PropertyChangeEvent(this, fieldName, oldValue, newValue)); - } - - /** - * Adds a VetoableChangeListener, which is notified of field - * changes. This is useful for an object that needs to update - * itself each time a field changes. - */ - public void addPropertyChangeListener(VetoableChangeListener listener) { - changeSupport.addVetoableChangeListener(listener); - } - - /** - * Removes a property listener. - */ - public void removePropertyChangeListener(VetoableChangeListener listener) { - changeSupport.removeVetoableChangeListener(listener); - } - /** * Returns a clone of this entry. Useful for copying. */ @@ -651,4 +602,13 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(type, fields); } + + public void registerListener(Object object) { + this.eventBus.register(object); + } + + public void unregisterListener(Object object) { + this.eventBus.unregister(object); + } + } diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java index e26ab9c0ea07..ee823acd4024 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java @@ -1,23 +1,29 @@ package net.sf.jabref.specialfields; import net.sf.jabref.JabRefGUI; +import net.sf.jabref.event.EntryAddedEvent; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.database.DatabaseChangeEvent; -import net.sf.jabref.model.database.DatabaseChangeListener; import net.sf.jabref.model.entry.BibEntry; -public class SpecialFieldDatabaseChangeListener implements - DatabaseChangeListener { +import com.google.common.eventbus.Subscribe; + +public class SpecialFieldDatabaseChangeListener { private static SpecialFieldDatabaseChangeListener INSTANCE; - @Override - public void databaseChanged(DatabaseChangeEvent e) { - if (e.getType() == DatabaseChangeEvent.ChangeType.ADDED_ENTRY && - SpecialFieldsUtils.keywordSyncEnabled()) { - final BibEntry entry = e.getEntry(); + public static SpecialFieldDatabaseChangeListener getInstance() { + if (SpecialFieldDatabaseChangeListener.INSTANCE == null) { + SpecialFieldDatabaseChangeListener.INSTANCE = new SpecialFieldDatabaseChangeListener(); + } + return SpecialFieldDatabaseChangeListener.INSTANCE; + } + + @Subscribe + public void listen(EntryAddedEvent EntryAddedEvent) { + if (SpecialFieldsUtils.keywordSyncEnabled()) { + final BibEntry entry = EntryAddedEvent.getBibEntry(); // NamedCompount code similar to SpecialFieldUpdateListener NamedCompound nc = new NamedCompound(Localization.lang("Synchronized special fields based on keywords")); SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, nc); @@ -26,11 +32,4 @@ public void databaseChanged(DatabaseChangeEvent e) { } } - public static SpecialFieldDatabaseChangeListener getInstance() { - if (SpecialFieldDatabaseChangeListener.INSTANCE == null) { - SpecialFieldDatabaseChangeListener.INSTANCE = new SpecialFieldDatabaseChangeListener(); - } - return SpecialFieldDatabaseChangeListener.INSTANCE; - } - } diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java index 54f56b254605..aa1eed50c411 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java @@ -15,30 +15,28 @@ */ package net.sf.jabref.specialfields; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyVetoException; -import java.beans.VetoableChangeListener; - import javax.swing.SwingUtilities; import net.sf.jabref.JabRefGUI; +import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.model.entry.BibEntry; +import com.google.common.eventbus.Subscribe; + /** * Listener triggering * * an update of keywords if special field has been updated * * an update of special fields if keywords have been updated */ -public class SpecialFieldUpdateListener implements VetoableChangeListener { +public class SpecialFieldUpdateListener { private static SpecialFieldUpdateListener INSTANCE; - - @Override - public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException { - final BibEntry entry = (BibEntry) e.getSource(); - final String fieldName = e.getPropertyName(); + @Subscribe + public void listen(FieldChangedEvent fieldChangedEvent) { + final BibEntry entry = fieldChangedEvent.getBibEntry(); + final String fieldName = fieldChangedEvent.getFieldName(); // Source editor cycles through all entries // if we immediately updated the fields, the entry editor would detect a subsequent change as a user change // and re-fire this event @@ -47,11 +45,13 @@ public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException { NamedCompound compound = new NamedCompound("SpecialFieldSync"); if ("keywords".equals(fieldName)) { SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, compound); - SwingUtilities.invokeLater(() -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); + SwingUtilities + .invokeLater(() -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); } else { if (SpecialFieldsUtils.isSpecialField(fieldName)) { SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, compound); - SwingUtilities.invokeLater(() -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); + SwingUtilities.invokeLater( + () -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); } } // we do NOT pass the named component to the undo manager since we do not want to have undo capabilities diff --git a/src/test/java/net/sf/jabref/event/TestEventListener.java b/src/test/java/net/sf/jabref/event/TestEventListener.java new file mode 100644 index 000000000000..63a424dd80b2 --- /dev/null +++ b/src/test/java/net/sf/jabref/event/TestEventListener.java @@ -0,0 +1,31 @@ +package net.sf.jabref.event; + +import net.sf.jabref.model.entry.BibEntry; + +import com.google.common.eventbus.Subscribe; + +public class TestEventListener { + + private BibEntry bibEntry; + + + @Subscribe + public void listen(EntryAddedEvent event) { + this.bibEntry = event.getBibEntry(); + } + + @Subscribe + public void listen(EntryRemovedEvent event) { + this.bibEntry = event.getBibEntry(); + } + + @Subscribe + public void listen(EntryChangedEvent event) { + this.bibEntry = event.getBibEntry(); + } + + public BibEntry getBibEntry() { + return this.bibEntry; + } + +} diff --git a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java index 65d9aac7a070..d20ad5d70336 100644 --- a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java +++ b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java @@ -8,6 +8,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.event.TestEventListener; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.entry.BibEntry; @@ -187,4 +188,27 @@ public void addSameStringIdTwiceThrowsKeyCollisionException() { database.addString(string); fail(); } + + @Test + public void testAddedEntryEventReceivement() { + BibDatabase database = new BibDatabase(); + BibEntry expectedEntry = new BibEntry(); + TestEventListener tel = new TestEventListener(); + database.registerListener(tel); + database.insertEntry(expectedEntry); + BibEntry actualEntry = tel.getBibEntry(); + assertEquals(expectedEntry, actualEntry); + } + + @Test + public void testRemovedEntryEventReceivement() { + BibDatabase database = new BibDatabase(); + BibEntry expectedEntry = new BibEntry(); + TestEventListener tel = new TestEventListener(); + database.insertEntry(expectedEntry); + database.registerListener(tel); + database.removeEntry(expectedEntry); + BibEntry actualEntry = tel.getBibEntry(); + assertEquals(expectedEntry, actualEntry); + } } From a98963808b21858cd72bf9bf9f426a521aead01d Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 14:56:26 +0200 Subject: [PATCH 022/268] Update .travis.yml --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2121cfdb511b..62ae3db4eff8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,9 @@ after_script: - bash <(curl -s https://codecov.io/bash) # cache gradle dependencies +# https://docs.travis-ci.com/user/languages/java#Caching +before_cache: + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock cache: directories: - $HOME/.gradle/caches/ From 2da1c98812b4dac1dba090498f88faf574face5d Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 15:24:30 +0200 Subject: [PATCH 023/268] Fix #1302: Create codecov yml based on suggestion from codecov.io --- codecov.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000000..96c12579acb6 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,5 @@ +coverage: + ignore: + - src/gen/.* + status: + patch: false From e34be5aa6aedfc39cb0709b4108ded6451450628 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 16:52:53 +0200 Subject: [PATCH 024/268] Fix #1327: PDF cleanup retains order of linked files --- CHANGELOG.md | 1 + .../logic/cleanup/FileLinksCleanup.java | 4 +-- .../logic/cleanup/MoveFilesCleanup.java | 10 ++++-- .../logic/cleanup/RelativePathsCleanup.java | 5 ++- .../logic/cleanup/RenamePdfCleanup.java | 16 +++++---- .../logic/cleanup/MoveFilesCleanupTest.java | 36 ++++++++++++++++--- .../logic/cleanup/RenamePdfCleanupTest.java | 17 +++++++++ 7 files changed, 72 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 632bb19892c4..77b200af7811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed [#1271](https://github.com/JabRef/jabref/issues/1271): Authors with compound first names are displayed properly - Fixed: Selecting invalid jstyle causes NPE and prevents opening of style selection dialog - Fixed: Move linked files to default directory works again +- Fixed [#1327](https://github.com/JabRef/jabref/issues/1327): PDF cleanup changes order of linked pdfs ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java index 3191150a2149..530dd846d0a9 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java @@ -33,7 +33,7 @@ public class FileLinksCleanup implements CleanupJob { public List cleanup(BibEntry entry) { Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); if (!oldValue.isPresent()) { - return new ArrayList<>(); + return Collections.emptyList(); } List fileList = FileField.parse(oldValue.get()); @@ -45,6 +45,6 @@ public List cleanup(BibEntry entry) { FieldChange change = new FieldChange(entry, Globals.FILE_FIELD, oldValue.get(), newValue); return Collections.singletonList(change); } - return new ArrayList<>(); + return Collections.emptyList(); } } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java index 90dd7b130373..9ff8cb2719ca 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java @@ -38,14 +38,14 @@ public MoveFilesCleanup(BibDatabaseContext databaseContext) { @Override public List cleanup(BibEntry entry) { if(!databaseContext.getMetaData().getDefaultFileDirectory().isPresent()) { - return new ArrayList<>(); + return Collections.emptyList(); } List paths = databaseContext.getFileDirectory(); String defaultFileDirectory = databaseContext.getMetaData().getDefaultFileDirectory().get(); Optional targetDirectory = FileUtil.expandFilename(defaultFileDirectory, paths); if(!targetDirectory.isPresent()) { - return new ArrayList<>(); + return Collections.emptyList(); } TypedBibEntry typedEntry = new TypedBibEntry(entry, databaseContext); @@ -57,12 +57,14 @@ public List cleanup(BibEntry entry) { Optional oldFile = FileUtil.expandFilename(oldFileName, paths); if(!oldFile.isPresent() || !oldFile.get().exists()) { + newFileList.add(fileEntry); continue; } File targetFile = new File(targetDirectory.get(), oldFile.get().getName()); if(targetFile.exists()) { // We do not overwrite already existing files + newFileList.add(fileEntry); continue; } @@ -76,6 +78,7 @@ public List cleanup(BibEntry entry) { } newFileList.add(newFileEntry); } + if (changed) { Optional change = typedEntry.setFiles(newFileList); if(change.isPresent()) { @@ -84,7 +87,8 @@ public List cleanup(BibEntry entry) { return Collections.emptyList(); } } - return new ArrayList<>(); + + return Collections.emptyList(); } } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java index 6dab36d2a4d8..5e5de2c9db1a 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java @@ -41,6 +41,7 @@ public List cleanup(BibEntry entry) { List fileList = typedEntry.getFiles(); List newFileList = new ArrayList<>(); boolean changed = false; + for (ParsedFileField fileEntry : fileList) { String oldFileName = fileEntry.getLink(); String newFileName = FileUtil.shortenFileName(new File(oldFileName), databaseContext.getFileDirectory()) @@ -53,6 +54,7 @@ public List cleanup(BibEntry entry) { } newFileList.add(newFileEntry); } + if (changed) { Optional change = typedEntry.setFiles(newFileList); if(change.isPresent()) { @@ -61,7 +63,8 @@ public List cleanup(BibEntry entry) { return Collections.emptyList(); } } - return new ArrayList<>(); + + return Collections.emptyList(); } } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java index f44ee537f70b..493836a3f1d8 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java @@ -31,13 +31,13 @@ public class RenamePdfCleanup implements CleanupJob { private final BibDatabaseContext databaseContext; - private final Boolean onlyRelativePaths; - private int unsuccessfulRenames; + private final boolean onlyRelativePaths; private final JournalAbbreviationRepository repository; + private int unsuccessfulRenames; - public RenamePdfCleanup(Boolean onlyRelativePaths, BibDatabaseContext databaseContext, - JournalAbbreviationRepository repository) { + public RenamePdfCleanup(boolean onlyRelativePaths, BibDatabaseContext databaseContext, + JournalAbbreviationRepository repository) { this.databaseContext = Objects.requireNonNull(databaseContext); this.onlyRelativePaths = onlyRelativePaths; this.repository = repository; @@ -49,10 +49,12 @@ public List cleanup(BibEntry entry) { List fileList = typedEntry.getFiles(); List newFileList = new ArrayList<>(); boolean changed = false; + for (ParsedFileField flEntry : fileList) { String realOldFilename = flEntry.getLink(); if (onlyRelativePaths && (new File(realOldFilename).isAbsolute())) { + newFileList.add(flEntry); continue; } @@ -69,19 +71,21 @@ public List cleanup(BibEntry entry) { databaseContext.getFileDirectory()); if ((!expandedOldFile.isPresent()) || (expandedOldFile.get().getParent() == null)) { // something went wrong. Just skip this entry + newFileList.add(flEntry); continue; } String newPath = expandedOldFile.get().getParent().concat(System.getProperty("file.separator")) .concat(newFilename.toString()); String expandedOldFilePath = expandedOldFile.get().toString(); - Boolean pathsDifferOnlyByCase = newPath.equalsIgnoreCase(expandedOldFilePath) && !newPath.equals( + boolean pathsDifferOnlyByCase = newPath.equalsIgnoreCase(expandedOldFilePath) && !newPath.equals( expandedOldFilePath); if (new File(newPath).exists() && ! pathsDifferOnlyByCase) { // we do not overwrite files // Since File.exists is sometimes not case-sensitive, the check pathsDifferOnlyByCase ensures that we // nonetheless rename files to a new name which just differs by case. // TODO: we could check here if the newPath file is linked with the current entry. And if not, we could add a link + newFileList.add(flEntry); continue; } @@ -122,7 +126,7 @@ public List cleanup(BibEntry entry) { } } - return new ArrayList<>(); + return Collections.emptyList(); } public int getUnsuccessfulRenames() { diff --git a/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java index adfde071def4..b48b79137e32 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; @@ -17,6 +18,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -44,17 +46,41 @@ public void setUp() throws IOException { @Test public void movesFileFromSubfolder() throws IOException { File subfolder = bibFolder.newFolder(); - File tempFile = new File(subfolder, "test.pdf"); - tempFile.createNewFile(); + File fileBefore = new File(subfolder, "test.pdf"); + assertTrue(fileBefore.createNewFile()); assertTrue(new File(subfolder, "test.pdf").exists()); BibEntry entry = new BibEntry(); - ParsedFileField fileField = new ParsedFileField("", tempFile.getAbsolutePath(), ""); + ParsedFileField fileField = new ParsedFileField("", fileBefore.getAbsolutePath(), ""); entry.setField("file", FileField.getStringRepresentation(fileField)); cleanup.cleanup(entry); - assertFalse(new File(subfolder, "test.pdf").exists()); - assertTrue(new File(pdfFolder, "test.pdf").exists()); + assertFalse(fileBefore.exists()); + File fileAfter = new File(pdfFolder, "test.pdf"); + assertTrue(fileAfter.exists()); + + assertEquals(FileField.getStringRepresentation(new ParsedFileField("", fileAfter.getName(), "")), entry.getField("file")); + } + + @Test + public void movesFileFromSubfolderMultiple() throws IOException { + File subfolder = bibFolder.newFolder(); + File fileBefore = new File(subfolder, "test.pdf"); + assertTrue(fileBefore.createNewFile());; + assertTrue(fileBefore.exists()); + + BibEntry entry = new BibEntry(); + ParsedFileField fileField = new ParsedFileField("", fileBefore.getAbsolutePath(), ""); + entry.setField("file", FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), fileField, new ParsedFileField("","","")))); + + cleanup.cleanup(entry); + + assertFalse(fileBefore.exists()); + File fileAfter = new File(pdfFolder, "test.pdf"); + assertTrue(fileAfter.exists()); + + assertEquals(FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), + new ParsedFileField("", fileAfter.getName(), ""), new ParsedFileField("","",""))), entry.getField("file")); } } \ No newline at end of file diff --git a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java index d21c60916953..46962684bdff 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; @@ -59,6 +60,22 @@ public void cleanupRenamePdfRenamesFileEvenIfOnlyDifferenceIsCase() throws IOExc assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); } + @Test + public void cleanupRenamePdfRenamesWithMultipleFiles() throws IOException { + when(Globals.prefs.get("importFileNamePattern")).thenReturn("\\bibtexkey - \\title"); + File tempFile = testFolder.newFile("Toot.tmp"); + + entry.setField("title", "test title"); + entry.setField("file", FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), + new ParsedFileField("", tempFile.getAbsolutePath(), ""), new ParsedFileField("","","")))); + + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationRepository.class)); + cleanup.cleanup(entry); + + assertEquals(FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), + new ParsedFileField("", "Toot - test title.tmp", ""), new ParsedFileField("","",""))), entry.getField("file")); + } + @Test public void cleanupRenamePdfRenamesFileStartingWithBibtexKey() throws IOException { when(Globals.prefs.get("importFileNamePattern")).thenReturn("\\bibtexkey - \\title"); From 56e3c4cf43d12a616869d56a9d4cd3670639f102 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 17:07:42 +0200 Subject: [PATCH 025/268] Remove unused import --- src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java index 530dd846d0a9..773af79878d7 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java @@ -13,7 +13,6 @@ */ package net.sf.jabref.logic.cleanup; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; From 1f5d8432156e255bb7165803bbe6c754ab754dca Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 17:25:01 +0200 Subject: [PATCH 026/268] Minor improvements --- .../java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java | 3 +-- .../java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java index 493836a3f1d8..7f511b4ace70 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java @@ -40,7 +40,7 @@ public RenamePdfCleanup(boolean onlyRelativePaths, BibDatabaseContext databaseCo JournalAbbreviationRepository repository) { this.databaseContext = Objects.requireNonNull(databaseContext); this.onlyRelativePaths = onlyRelativePaths; - this.repository = repository; + this.repository = Objects.requireNonNull(repository); } @Override @@ -60,7 +60,6 @@ public List cleanup(BibEntry entry) { StringBuilder newFilename = new StringBuilder( FileUtil.getLinkedFileName(databaseContext.getDatabase(), entry, repository)); - //String oldFilename = bes.getField(GUIGlobals.FILE_FIELD); // would have to be stored for undoing purposes //Add extension to newFilename newFilename.append('.').append(FileUtil.getFileExtension(realOldFilename).orElse("pdf")); diff --git a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java index 46962684bdff..df150f34c43e 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java @@ -93,7 +93,7 @@ public void cleanupRenamePdfRenamesFileStartingWithBibtexKey() throws IOExceptio @Test public void cleanupRenamePdfRenamesFileInSameFolder() throws IOException { - when(Globals.prefs.get("importFileNamePattern")).thenReturn("\\bibtexkey\\begin{title} - \\format[RemoveBrackets]{\\title}\\end{title}"); + when(Globals.prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)).thenReturn("\\bibtexkey\\begin{title} - \\format[RemoveBrackets]{\\title}\\end{title}"); testFolder.newFile("Toot.pdf"); ParsedFileField fileField = new ParsedFileField("", "Toot.pdf", "PDF"); entry.setField("file", FileField.getStringRepresentation(fileField)); From c040f5b980394c676e0aa78d5272509d147d4bb1 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 17:37:58 +0200 Subject: [PATCH 027/268] Fix #1122: Groups highlighting is enabled by default now --- src/main/java/net/sf/jabref/JabRefPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index c68c386e8ae8..e523f4e0d576 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -618,7 +618,7 @@ private JabRefPreferences() { defaults.put(AUTO_ASSIGN_GROUP, Boolean.TRUE); defaults.put(GROUP_KEYWORD_SEPARATOR, ", "); defaults.put(EDIT_GROUP_MEMBERSHIP_MODE, Boolean.FALSE); - defaults.put(HIGHLIGHT_GROUPS_MATCHING, ""); + defaults.put(HIGHLIGHT_GROUPS_MATCHING, "all"); defaults.put(TOOLBAR_VISIBLE, Boolean.TRUE); defaults.put(DEFAULT_ENCODING, StandardCharsets.UTF_8.name()); defaults.put(GROUPS_VISIBLE_ROWS, 8); From c1d10695c752d43d1da53975cece297f21a9ee46 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 9 May 2016 21:06:10 +0200 Subject: [PATCH 028/268] Normalize page cleanup also replaces em dash (#1348) --- .../formatter/bibtexfields/NormalizePagesFormatter.java | 2 +- .../formatter/bibtexfields/NormalizePagesFormatterTest.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java index 6186c0cc5cda..6fb2c3561c99 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java @@ -58,7 +58,7 @@ public String format(String value) { } // remove unwanted literals incl. whitespace - String cleanValue = value.replaceAll(REJECT_LITERALS, ""); + String cleanValue = value.replaceAll("\u2013|\u2014", "-").replaceAll(REJECT_LITERALS, ""); // try to find pages pattern Matcher matcher = PAGES_DETECT_PATTERN.matcher(cleanValue); // replace diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java index e0aca3dbe05d..3af98a853c46 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java @@ -60,6 +60,11 @@ public void doesNotRemoveLetters() { expectCorrect("R1-R50", "R1-R50"); } + @Test + public void replacesLongDashWithDoubleDash() { + expectCorrect("1 \u2014 50", "1--50"); + } + @Test public void formatExample() { expectCorrect(formatter.getExampleInput(), "1--2"); From 57d90d1dd2056fbd7788df29d7df3962eba02cf0 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:06:54 +0200 Subject: [PATCH 029/268] Use Objects.equals --- .../net/sf/jabref/gui/actions/ManageKeywordsAction.java | 3 ++- .../java/net/sf/jabref/gui/entryeditor/EntryEditor.java | 4 ++-- .../java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java | 3 ++- .../net/sf/jabref/gui/groups/GroupTreeCellRenderer.java | 5 +++-- .../net/sf/jabref/logic/labelpattern/LabelPatternUtil.java | 7 ++++--- src/main/java/net/sf/jabref/model/entry/BibEntry.java | 2 +- .../net/sf/jabref/specialfields/SpecialFieldsUtils.java | 3 ++- 7 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java index 599fb1c1131a..18c09923166c 100644 --- a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java @@ -23,6 +23,7 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; @@ -329,7 +330,7 @@ private NamedCompound updateKeywords(List entries, Set keyword String oldValue = entry.getField(KEYWORDS_FIELD); entry.putKeywords(separatedKeywords); String updatedValue = entry.getField(KEYWORDS_FIELD); - if ((oldValue == null) || !oldValue.equals(updatedValue)) { + if (!Objects.equals(oldValue, updatedValue)) { ce.addEdit(new UndoableFieldChange(entry, KEYWORDS_FIELD, oldValue, updatedValue)); } diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 250d781be1f3..d2b76a86cceb 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -809,7 +809,7 @@ private boolean storeSource() { for (String field : newEntry.getFieldNames()) { String oldValue = entry.getField(field); String newValue = newEntry.getField(field); - if ((oldValue == null) || !oldValue.equals(newValue)) { + if (!Objects.equals(oldValue, newValue)) { // Test if the field is legally set. new LatexFieldFormatter().format(newValue, field); @@ -1089,7 +1089,7 @@ public void actionPerformed(ActionEvent event) { newValue = null; } - if (((oldValue == null) && (newValue == null)) || ((oldValue != null) && oldValue.equals(newValue))) { + if (((oldValue == null) && (newValue == null)) || (Objects.equals(oldValue, newValue))) { return; // No change. } diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java index 795a2067d5ee..b4ff29f84abf 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -225,7 +226,7 @@ private boolean isFieldModified(FieldEditor fieldEditor) { return getEntry().hasField(fieldEditor.getFieldName()); } else { String entryValue = getEntry().getField(fieldEditor.getFieldName()); - return (entryValue == null) || !entryValue.equals(text); + return !Objects.equals(entryValue, text); } } diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java index ec3384894e2d..e3b1d31fd31d 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java @@ -17,6 +17,7 @@ import java.awt.Color; import java.awt.Component; +import java.util.Objects; import javax.swing.BorderFactory; import javax.swing.Icon; @@ -44,7 +45,7 @@ public class GroupTreeCellRenderer extends DefaultTreeCellRenderer { public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean tmpHasFocus) { // show as selected - selected = ((highlight1Cell != null) && highlight1Cell.equals(value)) || sel; + selected = (Objects.equals(highlight1Cell, value)) || sel; Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, tmpHasFocus); // this is sometimes called from deep within somewhere, with a dummy // value (probably for layout etc.), so we've got to check here! @@ -58,7 +59,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean GroupTreeNodeViewModel viewModel = (GroupTreeNodeViewModel) value; JLabel label = (JLabel) c; - if ((highlightBorderCell != null) && (highlightBorderCell.equals(value))) { + if (Objects.equals(highlightBorderCell, value)) { label.setBorder(BorderFactory.createLineBorder(Color.BLACK)); } else { label.setBorder(BorderFactory.createEmptyBorder()); diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index 13bbb7e6ea55..1ca740b8a408 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -488,7 +489,7 @@ public static void makeLabel(MetaData metaData, BibDatabase dBase, BibEntry entr String oldKey = entry.getCiteKey(); int occurrences = database.getNumberOfKeyOccurrences(key); - if ((oldKey != null) && oldKey.equals(key)) { + if (Objects.equals(oldKey, key)) { occurrences--; // No change, so we can accept one dupe. } @@ -516,7 +517,7 @@ public static void makeLabel(MetaData metaData, BibDatabase dBase, BibEntry entr String moddedKey = key + getAddition(number); occurrences = database.getNumberOfKeyOccurrences(moddedKey); - if ((oldKey != null) && oldKey.equals(moddedKey)) { + if (Objects.equals(oldKey, moddedKey)) { occurrences--; } @@ -525,7 +526,7 @@ public static void makeLabel(MetaData metaData, BibDatabase dBase, BibEntry entr moddedKey = key + getAddition(number); occurrences = database.getNumberOfKeyOccurrences(moddedKey); - if ((oldKey != null) && oldKey.equals(moddedKey)) { + if (Objects.equals(oldKey, moddedKey)) { occurrences--; } } diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 0bca1fcd8381..bbafde8e389e 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -528,7 +528,7 @@ public void putKeywords(List keywords) { } return; } - if ((oldValue == null) || !oldValue.equals(newValue)) { + if (!Objects.equals(oldValue, newValue)) { this.setField("keywords", newValue); } } diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java index 4d7269272b39..9867873ff908 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java @@ -16,6 +16,7 @@ package net.sf.jabref.specialfields; import java.util.List; +import java.util.Objects; import net.sf.jabref.Globals; import net.sf.jabref.gui.undo.NamedCompound; @@ -115,7 +116,7 @@ private static void exportFieldToKeywords(SpecialField e, String newValue, BibEn String oldValue = be.getField(KEYWORDS_FIELD); be.putKeywords(keywordList); String updatedValue = be.getField(KEYWORDS_FIELD); - if (((oldValue == null) || !oldValue.equals(updatedValue)) && (ce != null)) { + if ((!Objects.equals(oldValue, updatedValue)) && (ce != null)) { ce.addEdit(new UndoableFieldChange(be, KEYWORDS_FIELD, oldValue, updatedValue)); } From 4223bc6a23d9d804c43353930c544b406b4239cb Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:07:54 +0200 Subject: [PATCH 030/268] Use Map.putIfAbsent --- .../net/sf/jabref/importer/fileformat/EndnoteImporter.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java index 1136ac5402bf..dbd5b0cc8adc 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java @@ -193,9 +193,7 @@ public List importEntries(InputStream stream, OutputPrinter status) th } else if ("J".equals(prefix)) { // "Alternate journal. Let's set it only if no journal // has been set with %B. - if (hm.get("journal") == null) { - hm.put("journal", val); - } + hm.putIfAbsent("journal", val); } else if ("B".equals(prefix)) { // This prefix stands for "journal" in a journal entry, and // "series" in a book entry. From 3b0d38e12f0de65a4542f17f4d6c486e6c702f97 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:09:39 +0200 Subject: [PATCH 031/268] Use lambdas instead of anonymous classes --- .../net/sf/jabref/JabRefExecutorService.java | 11 +++----- .../jabref/external/DroppedFileHandler.java | 10 +++---- .../jabref/importer/AppendDatabaseAction.java | 12 ++------- .../jabref/importer/OpenDatabaseAction.java | 8 +----- .../net/sf/jabref/model/entry/BibEntry.java | 2 +- .../net/sf/jabref/bst/BibtexPurifyTest.java | 9 ++----- .../sf/jabref/bst/TextPrefixFunctionTest.java | 9 ++----- .../layout/format/CompositeFormatTest.java | 26 +++---------------- 8 files changed, 19 insertions(+), 68 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefExecutorService.java b/src/main/java/net/sf/jabref/JabRefExecutorService.java index 56be64be6a1b..79e67a2cd805 100644 --- a/src/main/java/net/sf/jabref/JabRefExecutorService.java +++ b/src/main/java/net/sf/jabref/JabRefExecutorService.java @@ -37,13 +37,10 @@ public class JabRefExecutorService implements Executor { public static final JabRefExecutorService INSTANCE = new JabRefExecutorService(); - private final ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r); - thread.setName("JabRef CachedThreadPool"); - return thread; - } + private final ExecutorService executorService = Executors.newCachedThreadPool(r -> { + Thread thread = new Thread(r); + thread.setName("JabRef CachedThreadPool"); + return thread; }); private final ConcurrentLinkedQueue startedThreads = new ConcurrentLinkedQueue<>(); diff --git a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java index b33cafa3f34b..217e3ca9d88a 100644 --- a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java +++ b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java @@ -339,13 +339,9 @@ private boolean showLinkMoveCopyRenameDialog(String linkFileName, ExternalFileTy renameCheckBox.setEnabled(true); } - ChangeListener cl = new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent arg0) { - renameCheckBox.setEnabled(!linkInPlace.isSelected()); - renameToTextBox.setEnabled(!linkInPlace.isSelected()); - } + ChangeListener cl = arg0 -> { + renameCheckBox.setEnabled(!linkInPlace.isSelected()); + renameToTextBox.setEnabled(!linkInPlace.isSelected()); }; linkInPlace.setText(Localization.lang("Leave file in its current directory")); diff --git a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java index a6d7508c9c90..df5e356c70b3 100644 --- a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java @@ -94,16 +94,8 @@ public void action() { // Run the actual open in a thread to prevent the program // locking until the file is loaded. - JabRefExecutorService.INSTANCE.execute(new Runnable() { - - @Override - public void run() { - openIt(md.importEntries(), md.importStrings(), - md.importGroups(), md.importSelectorWords()); - } - - }); - //frame.getFileHistory().newFile(panel.fileToOpen.getPath()); + JabRefExecutorService.INSTANCE.execute(() -> openIt(md.importEntries(), md.importStrings(), + md.importGroups(), md.importSelectorWords())); } } diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index 0eda6fd7275c..74b15fc2d385 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -305,13 +305,7 @@ private void openTheFile(File file, boolean raisePanel) { // if the database contents should be modified due to new features // in this version of JabRef: final ParserResult finalReferenceToResult = result; - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - OpenDatabaseAction.performPostOpenActions(panel, finalReferenceToResult, true); - } - }); + SwingUtilities.invokeLater(() -> OpenDatabaseAction.performPostOpenActions(panel, finalReferenceToResult, true)); } } diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index bbafde8e389e..9818269164fa 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -328,7 +328,7 @@ public Date parse(String source, ParsePosition pos) { public void setField(Map fields) { Objects.requireNonNull(fields, "fields must not be null"); - fields.forEach((field, value) -> setField(field, value)); + fields.forEach(this::setField); } /** diff --git a/src/test/java/net/sf/jabref/bst/BibtexPurifyTest.java b/src/test/java/net/sf/jabref/bst/BibtexPurifyTest.java index 1512aeb49e44..95756761c9f3 100644 --- a/src/test/java/net/sf/jabref/bst/BibtexPurifyTest.java +++ b/src/test/java/net/sf/jabref/bst/BibtexPurifyTest.java @@ -19,12 +19,7 @@ public void testPurify() { } private void assertPurify(final String string, final String string2) { - Assert.assertEquals(string, BibtexPurify.purify(string2, new Warn() { - - @Override - public void warn(String s) { - Assert.fail("Should not Warn (" + s + ")! purify should be " + string + " for " + string2); - } - })); + Assert.assertEquals(string, BibtexPurify.purify(string2, s -> + Assert.fail("Should not Warn (" + s + ")! purify should be " + string + " for " + string2))); } } diff --git a/src/test/java/net/sf/jabref/bst/TextPrefixFunctionTest.java b/src/test/java/net/sf/jabref/bst/TextPrefixFunctionTest.java index 2c1c34599c15..d24601cf6ef2 100644 --- a/src/test/java/net/sf/jabref/bst/TextPrefixFunctionTest.java +++ b/src/test/java/net/sf/jabref/bst/TextPrefixFunctionTest.java @@ -19,13 +19,8 @@ public void testPrefix() { } private static void assertPrefix(final String string, final String string2) { - Assert.assertEquals(string, BibtexTextPrefix.textPrefix(5, string2, new Warn() { - - @Override - public void warn(String s) { - Assert.fail("Should not Warn! text.prefix$ should be " + string + " for (5) " + string2); - } - })); + Assert.assertEquals(string, BibtexTextPrefix.textPrefix(5, string2, s -> + Assert.fail("Should not Warn! text.prefix$ should be " + string + " for (5) " + string2))); } } diff --git a/src/test/java/net/sf/jabref/logic/layout/format/CompositeFormatTest.java b/src/test/java/net/sf/jabref/logic/layout/format/CompositeFormatTest.java index 41a67776a75c..94fc5b4f3266 100644 --- a/src/test/java/net/sf/jabref/logic/layout/format/CompositeFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/format/CompositeFormatTest.java @@ -15,28 +15,10 @@ public void testComposite() { Assert.assertEquals("No Change", f.format("No Change")); } { - LayoutFormatter f = new CompositeFormat(new LayoutFormatter[] {new LayoutFormatter() { - - @Override - public String format(String fieldText) { - return fieldText + fieldText; - } - - }, new LayoutFormatter() { - - @Override - public String format(String fieldText) { - return "A" + fieldText; - } - - }, new LayoutFormatter() { - - @Override - public String format(String fieldText) { - return "B" + fieldText; - } - - }}); + LayoutFormatter f = new CompositeFormat(new LayoutFormatter[] { + fieldText -> fieldText + fieldText, + fieldText -> "A" + fieldText, + fieldText -> "B" + fieldText}); Assert.assertEquals("BAff", f.format("f")); } From 8d6305e3058dbf78b3dfa75067f35736ea564184 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:12:21 +0200 Subject: [PATCH 032/268] Use lambdas instead of anonymous methods --- .../net/sf/jabref/bibtex/BibEntryWriter.java | 2 +- src/main/java/net/sf/jabref/bst/VM.java | 12 ++---- .../sf/jabref/gui/ImportInspectionDialog.java | 2 +- .../sf/jabref/gui/groups/GroupSelector.java | 42 +++---------------- .../sf/jabref/gui/openoffice/OOBibBase.java | 4 +- .../sf/jabref/logic/groups/GroupsUtil.java | 3 +- .../net/sf/jabref/logic/msbib/MSBibEntry.java | 4 +- .../net/sf/jabref/model/entry/AuthorList.java | 2 +- 8 files changed, 18 insertions(+), 53 deletions(-) diff --git a/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java b/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java index f6197a5f9bd2..73aa131ddc4d 100644 --- a/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java +++ b/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java @@ -153,7 +153,7 @@ private void writeField(BibEntry entry, Writer out, String name, int indentation private int getLengthOfLongestFieldName(BibEntry entry) { Predicate isNotBibtexKey = field -> !"bibtexkey".equals(field); - return entry.getFieldNames().stream().filter(isNotBibtexKey).mapToInt(field -> field.length()).max().orElse(0); + return entry.getFieldNames().stream().filter(isNotBibtexKey).mapToInt(String::length).max().orElse(0); } /** diff --git a/src/main/java/net/sf/jabref/bst/VM.java b/src/main/java/net/sf/jabref/bst/VM.java index 7961a96ef351..478526acd625 100644 --- a/src/main/java/net/sf/jabref/bst/VM.java +++ b/src/main/java/net/sf/jabref/bst/VM.java @@ -618,7 +618,7 @@ public void execute(BstEntry context) { * second as long as the (integer) literal left on the stack by * executing the first is greater than 0. */ - buildInFunctions.put("while$", context -> whileFunction(context)); + buildInFunctions.put("while$", this::whileFunction); buildInFunctions.put("width$", new WidthFunction(this)); @@ -1049,14 +1049,8 @@ private void iterate(Tree child) { * Sorts the entry list using the values of the string entry variable sort.key$. It has no arguments. */ private void sort() { - Collections.sort(entries, new Comparator() { - - @Override - public int compare(BstEntry o1, BstEntry o2) { - return (o1.localStrings.get("sort.key$")).compareTo(o2.localStrings - .get("sort.key$")); - } - }); + Collections.sort(entries, (o1, o2) -> (o1.localStrings.get("sort.key$")) + .compareTo(o2.localStrings.get("sort.key$"))); } private void executeInContext(Object o, BstEntry context) { diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index c6a09afa22bd..ad7376347bf5 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -809,7 +809,7 @@ private List getSelectedEntries() { } private void signalStopFetching() { - callBacks.forEach(c -> c.stopFetching()); + callBacks.forEach(CallBack::stopFetching); } private void setWidths() { diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index b2c824f972bc..16325c4d79e1 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -161,27 +161,9 @@ public GroupSelector(JabRefFrame frame, SidePaneManager manager) { ButtonGroup nonHits = new ButtonGroup(); nonHits.add(hideNonHits); nonHits.add(grayOut); - floatCb.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent event) { - Globals.prefs.putBoolean(JabRefPreferences.GROUP_FLOAT_SELECTIONS, floatCb.isSelected()); - } - }); - andCb.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent event) { - Globals.prefs.putBoolean(JabRefPreferences.GROUP_INTERSECT_SELECTIONS, andCb.isSelected()); - } - }); - invCb.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent event) { - Globals.prefs.putBoolean(JabRefPreferences.GROUP_INVERT_SELECTIONS, invCb.isSelected()); - } - }); + floatCb.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_FLOAT_SELECTIONS, floatCb.isSelected())); + andCb.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_INTERSECT_SELECTIONS, andCb.isSelected())); + invCb.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_INVERT_SELECTIONS, invCb.isSelected())); showOverlappingGroups.addChangeListener(new ChangeListener() { @Override @@ -193,13 +175,7 @@ public void stateChanged(ChangeEvent event) { } }); - select.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent event) { - Globals.prefs.putBoolean(JabRefPreferences.GROUP_SELECT_MATCHES, select.isSelected()); - } - }); + select.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_SELECT_MATCHES, select.isSelected())); grayOut.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.GRAY_OUT_NON_HITS, grayOut.isSelected())); JRadioButtonMenuItem highlCb = new JRadioButtonMenuItem(Localization.lang("Highlight"), false); @@ -233,13 +209,7 @@ public void stateChanged(ChangeEvent e) { } }); - autoAssignGroup.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent event) { - Globals.prefs.putBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP, autoAssignGroup.isSelected()); - } - }); + autoAssignGroup.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP, autoAssignGroup.isSelected())); invCb.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_INVERT_SELECTIONS)); showOverlappingGroups.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_OVERLAPPING)); @@ -637,7 +607,7 @@ public void valueChanged(TreeSelectionEvent e) { if (panel == null) { return; // ignore this event (happens for example if the file was closed) } - if (getLeafsOfSelection().stream().allMatch(node -> node.isAllEntriesGroup())) { + if (getLeafsOfSelection().stream().allMatch(GroupTreeNodeViewModel::isAllEntriesGroup)) { panel.mainTable.getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); if (showOverlappingGroups.isSelected()) { groupsTree.setHighlight2Cells(null); diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java index 521e0774c100..d6053cf3900e 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java @@ -329,7 +329,7 @@ public void insertEntry(List entries, BibDatabase database, } String keyString = String.join(",", - entries.stream().map(entry -> entry.getCiteKey()).collect(Collectors.toList())); + entries.stream().map(BibEntry::getCiteKey).collect(Collectors.toList())); // Insert bookmark: String bName = getUniqueReferenceMarkName(keyString, withText ? inParenthesis ? OOBibBase.AUTHORYEAR_PAR : OOBibBase.AUTHORYEAR_INTEXT : OOBibBase.INVISIBLE_CIT); @@ -1211,7 +1211,7 @@ public void combineCiteMarkers(List databases, OOBibStyle style) th } Collections.sort(entries, new FieldComparator("year")); String keyString = String.join(",", - entries.stream().map(entry -> entry.getCiteKey()).collect(Collectors.toList())); + entries.stream().map(BibEntry::getCiteKey).collect(Collectors.toList())); // Insert bookmark: String bName = getUniqueReferenceMarkName(keyString, OOBibBase.AUTHORYEAR_PAR); insertReferenceMark(bName, "tmp", mxDocCursor, true, style); diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java b/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java index e953226c44bf..abc5f27210b5 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java @@ -7,6 +7,7 @@ import java.util.stream.Collectors; import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -63,7 +64,7 @@ public static Set findAuthorLastNames(BibDatabase db, List field String val = be.getField(field); if ((val != null) && !val.isEmpty()) { AuthorList al = AuthorList.parse(val); - res.addAll(al.getAuthors().stream().map(author -> author.getLast()) + res.addAll(al.getAuthors().stream().map(Author::getLast) .filter(lastName -> ((lastName != null) && !lastName.isEmpty())) .collect(Collectors.toList())); } diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java index 3f7a0fec0362..5a3ff1a5b233 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java @@ -218,7 +218,7 @@ private void populateFromXml(Element entry, String bcol) { String city = getFromXml(bcol + "City", entry); String state = getFromXml(bcol + "StateProvince", entry); String country = getFromXml(bcol + "CountryRegion", entry); - StringBuffer addressBuffer = new StringBuffer(); + StringBuilder addressBuffer = new StringBuilder(); if (city != null) { addressBuffer.append(city).append(", "); } @@ -859,7 +859,7 @@ private void addAuthor(Map map, String type, List au if (authors == null) { return; } - String allAuthors = authors.stream().map(name -> name.getFullname()).collect(Collectors.joining(" and ")); + String allAuthors = authors.stream().map(PersonName::getFullname).collect(Collectors.joining(" and ")); map.put(type, allAuthors); } diff --git a/src/main/java/net/sf/jabref/model/entry/AuthorList.java b/src/main/java/net/sf/jabref/model/entry/AuthorList.java index a85b6b9c7415..bc152f282de5 100644 --- a/src/main/java/net/sf/jabref/model/entry/AuthorList.java +++ b/src/main/java/net/sf/jabref/model/entry/AuthorList.java @@ -587,7 +587,7 @@ public String getForAlphabetization() { return authorsAlph; } - authorsAlph = getAuthors().stream().map(author -> author.getNameForAlphabetization()) + authorsAlph = getAuthors().stream().map(Author::getNameForAlphabetization) .collect(Collectors.joining(" and ")); return authorsAlph; } From d9bfbbf3a32d364386e3abcb40974b6ba50d646d Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:23:17 +0200 Subject: [PATCH 033/268] More refactorings --- .../net/sf/jabref/JabRefExecutorService.java | 1 - .../net/sf/jabref/bibtex/BibEntryWriter.java | 4 +--- src/main/java/net/sf/jabref/bst/VM.java | 1 - .../net/sf/jabref/collab/ChangeScanner.java | 4 ++-- .../jabref/exporter/SaveDatabaseAction.java | 6 +++--- .../jabref/external/DownloadExternalFile.java | 2 +- .../sf/jabref/external/push/PushToLyx.java | 2 +- .../java/net/sf/jabref/gui/FileDialogs.java | 2 +- .../sf/jabref/gui/FileListEntryEditor.java | 3 +-- .../java/net/sf/jabref/gui/JabRefFrame.java | 3 ++- .../gui/actions/MnemonicAwareAction.java | 2 +- .../FileListEditorTransferHandler.java | 2 +- .../gui/groups/EntryTableTransferHandler.java | 20 ++++++++----------- .../jabref/gui/maintable/MainTableFormat.java | 3 ++- .../maintable/MainTableSelectionListener.java | 2 +- .../maintable/SpecialMainTableColumns.java | 18 ++++++++--------- .../sf/jabref/gui/openoffice/OOBibBase.java | 2 +- .../gui/openoffice/OpenOfficePanel.java | 1 - .../gui/openoffice/StyleSelectDialog.java | 2 +- .../sf/jabref/importer/CustomImporter.java | 2 +- .../net/sf/jabref/importer/ImportFormats.java | 4 ++-- .../jabref/importer/OpenDatabaseAction.java | 2 +- .../bibtexfields/UnicodeToLatexFormatter.java | 2 +- .../sf/jabref/logic/groups/GroupsUtil.java | 2 +- .../sf/jabref/logic/layout/LayoutEntry.java | 5 +++-- .../jabref/logic/layout/format/FileLink.java | 4 ++-- .../logic/layout/format/WrapFileLinks.java | 4 ++-- .../SearchQueryHighlightObservable.java | 4 ++-- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 5 ++--- 29 files changed, 53 insertions(+), 61 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefExecutorService.java b/src/main/java/net/sf/jabref/JabRefExecutorService.java index 79e67a2cd805..4ef232ffc5b5 100644 --- a/src/main/java/net/sf/jabref/JabRefExecutorService.java +++ b/src/main/java/net/sf/jabref/JabRefExecutorService.java @@ -21,7 +21,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.concurrent.ThreadFactory; import net.sf.jabref.gui.undo.UndoableInsertEntry; diff --git a/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java b/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java index 73aa131ddc4d..5e4cf86f5586 100644 --- a/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java +++ b/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java @@ -137,9 +137,7 @@ private void writeField(BibEntry entry, Writer out, String name, int indentation String field = entry.getField(name); // only write field if is is not empty or if empty fields should be included // the first condition mirrors mirror behavior of com.jgoodies.common.base.Strings.isNotBlank(str) - if (Strings.nullToEmpty(field).trim().isEmpty()) { - return; - } else { + if (!Strings.nullToEmpty(field).trim().isEmpty()) { out.write(" " + getFieldDisplayName(name, indentation)); try { diff --git a/src/main/java/net/sf/jabref/bst/VM.java b/src/main/java/net/sf/jabref/bst/VM.java index 478526acd625..0d97dd27bbd2 100644 --- a/src/main/java/net/sf/jabref/bst/VM.java +++ b/src/main/java/net/sf/jabref/bst/VM.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.ListIterator; diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index 51c036912795..edb8ac72ed4f 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -138,7 +138,7 @@ public boolean changesFound() { public void displayResult(final DisplayResultCallback fup) { if (changes.getChildCount() > 0) { - SwingUtilities.invokeLater((Runnable) () -> { + SwingUtilities.invokeLater(() -> { ChangeDisplayDialog dial = new ChangeDisplayDialog(frame, panel, inTemp, changes); dial.setLocationRelativeTo(frame); dial.setVisible(true); @@ -157,7 +157,7 @@ public void displayResult(final DisplayResultCallback fup) { } private void storeTempDatabase() { - JabRefExecutorService.INSTANCE.execute((Runnable) () -> { + JabRefExecutorService.INSTANCE.execute(() -> { try { SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs).withMakeBackup(false) .withEncoding(panel.getEncoding()); diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java index 20ca611653ff..8577e75d45c9 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java @@ -382,7 +382,7 @@ private boolean checkExternalModification() { } else if (answer == JOptionPane.YES_OPTION) { canceled = true; - JabRefExecutorService.INSTANCE.execute((Runnable) () -> { + JabRefExecutorService.INSTANCE.execute(() -> { if (!FileBasedLock.waitForFileLock(panel.getBibDatabaseContext().getDatabaseFile(), 10)) { // TODO: GUI handling of the situation when the externally modified file keeps being locked. @@ -393,11 +393,11 @@ private boolean checkExternalModification() { panel.getBibDatabaseContext().getDatabaseFile()); JabRefExecutorService.INSTANCE.executeWithLowPriorityInOwnThreadAndWait(scanner); if (scanner.changesFound()) { - scanner.displayResult((ChangeScanner.DisplayResultCallback) resolved -> { + scanner.displayResult(resolved -> { if (resolved) { panel.setUpdatedExternally(false); SwingUtilities - .invokeLater((Runnable) () -> panel.getSidePaneManager().hide("fileUpdate")); + .invokeLater(() -> panel.getSidePaneManager().hide("fileUpdate")); } else { canceled = true; } diff --git a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java index 8aa9c6a5f081..140502dd670a 100644 --- a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java +++ b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java @@ -123,7 +123,7 @@ public void download(URL url, final DownloadCallback callback) throws IOExceptio final URL urlF = url; final URLDownload udlF = udl; - JabRefExecutorService.INSTANCE.execute((Runnable) () -> { + JabRefExecutorService.INSTANCE.execute(() -> { try { udlF.downloadToFile(tmp); } catch (IOException e2) { diff --git a/src/main/java/net/sf/jabref/external/push/PushToLyx.java b/src/main/java/net/sf/jabref/external/push/PushToLyx.java index 8ee32d18e2f0..6df3a0b5b882 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToLyx.java +++ b/src/main/java/net/sf/jabref/external/push/PushToLyx.java @@ -112,7 +112,7 @@ public void pushEntries(BibDatabase database, final List entries, fina final File lyxpipe = lp; - JabRefExecutorService.INSTANCE.executeAndWait((Runnable) () -> { + JabRefExecutorService.INSTANCE.executeAndWait(() -> { try (FileWriter fw = new FileWriter(lyxpipe); BufferedWriter lyxOut = new BufferedWriter(fw)) { String citeStr; diff --git a/src/main/java/net/sf/jabref/gui/FileDialogs.java b/src/main/java/net/sf/jabref/gui/FileDialogs.java index ca7bd547098c..087b6eca5ac7 100644 --- a/src/main/java/net/sf/jabref/gui/FileDialogs.java +++ b/src/main/java/net/sf/jabref/gui/FileDialogs.java @@ -67,7 +67,7 @@ public static List getMultipleFiles(JFrame owner, File directory, String // Fix for: // http://sourceforge.net/tracker/index.php?func=detail&aid=1538769&group_id=92314&atid=600306 if (files != null) { - return Arrays.asList((String) files); + return Collections.singletonList((String) files); } return Collections.emptyList(); } diff --git a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java index cc82f8da0830..75cd2786ea80 100644 --- a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java @@ -317,8 +317,7 @@ private void storeSettings(FileListEntry entry) { if (fl.isAbsolute()) { String flPath = fl.getCanonicalPath(); if ((flPath.length() > canPath.length()) && (flPath.startsWith(canPath))) { - String relFileName = fl.getCanonicalPath().substring(canPath.length() + 1); - link = relFileName; + link = fl.getCanonicalPath().substring(canPath.length() + 1); found = true; break; } diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 5693a0856c45..23027c4504a0 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -34,6 +34,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -1558,7 +1559,7 @@ dupliCheck, autoSetFile, newEntryAction, plainTextImport, getMassSetField(), get severalDatabasesOnlyActions.addAll(Arrays .asList(nextTab, prevTab, sortTabs)); - openAndSavedDatabasesOnlyActions.addAll(Arrays.asList(openConsole)); + openAndSavedDatabasesOnlyActions.addAll(Collections.singletonList(openConsole)); tabbedPane.addChangeListener(event -> updateEnabledState()); diff --git a/src/main/java/net/sf/jabref/gui/actions/MnemonicAwareAction.java b/src/main/java/net/sf/jabref/gui/actions/MnemonicAwareAction.java index 81cba9dcf8b3..762d14219592 100644 --- a/src/main/java/net/sf/jabref/gui/actions/MnemonicAwareAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/MnemonicAwareAction.java @@ -48,7 +48,7 @@ public void putValue(String key, Object value) { int i = name.indexOf('&'); if (i >= 0) { char mnemonic = Character.toUpperCase(name.charAt(i + 1)); - putValue(Action.MNEMONIC_KEY, Integer.valueOf(mnemonic)); + putValue(Action.MNEMONIC_KEY, (int) mnemonic); value = name.substring(0, i) + name.substring(i + 1); } else { value = name; diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditorTransferHandler.java b/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditorTransferHandler.java index 5774e3edc51a..0f242b42eedf 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditorTransferHandler.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditorTransferHandler.java @@ -111,7 +111,7 @@ public boolean importData(JComponent comp, Transferable t) { files.addAll(EntryTableTransferHandler.getFilesFromDraggedFilesString(dropStr)); } - SwingUtilities.invokeLater((Runnable) () -> { + SwingUtilities.invokeLater(() -> { for (File file : files) { // Find the file's extension, if any: String name = file.getAbsolutePath(); diff --git a/src/main/java/net/sf/jabref/gui/groups/EntryTableTransferHandler.java b/src/main/java/net/sf/jabref/gui/groups/EntryTableTransferHandler.java index 1dc0f43fde32..3ee673e33834 100644 --- a/src/main/java/net/sf/jabref/gui/groups/EntryTableTransferHandler.java +++ b/src/main/java/net/sf/jabref/gui/groups/EntryTableTransferHandler.java @@ -29,7 +29,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -241,7 +241,7 @@ private boolean handleDropTransfer(String dropStr, final int dropRow) throws IOE // System.out.println("importing from " + tmpfile.getAbsolutePath()); ImportMenuItem importer = new ImportMenuItem(frame, false); - importer.automatedImport(Arrays.asList(tmpfile.getAbsolutePath())); + importer.automatedImport(Collections.singletonList(tmpfile.getAbsolutePath())); return true; } @@ -324,15 +324,11 @@ private boolean handleDraggedFiles(List files, final int dropRow) { // Try to load bib files normally, and import the rest into the current // database. // This process must be spun off into a background thread: - JabRefExecutorService.INSTANCE.execute(new Runnable() { - - @Override - public void run() { - final ImportPdfFilesResult importRes = new PdfImporter(frame, panel, entryTable, dropRow) - .importPdfFiles(fileNames); - if (!importRes.getNoPdfFiles().isEmpty()) { - loadOrImportFiles(importRes.getNoPdfFiles(), dropRow); - } + JabRefExecutorService.INSTANCE.execute(() -> { + final ImportPdfFilesResult importRes = new PdfImporter(frame, panel, entryTable, dropRow) + .importPdfFiles(fileNames); + if (!importRes.getNoPdfFiles().isEmpty()) { + loadOrImportFiles(importRes.getNoPdfFiles(), dropRow); } }); @@ -404,7 +400,7 @@ private boolean handleDropTransfer(URL dropLink) throws IOException { // Import into new if entryTable==null, otherwise into current database: ImportMenuItem importer = new ImportMenuItem(frame, entryTable == null); - importer.automatedImport(Arrays.asList(tmpfile.getAbsolutePath())); + importer.automatedImport(Collections.singletonList(tmpfile.getAbsolutePath())); return true; } diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java index ff2d30cc931e..31917d384126 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import javax.swing.JLabel; @@ -43,7 +44,7 @@ public class MainTableFormat implements TableFormat { // These values are also used to put a heading into the table; see getColumnName(int) private static final List URL_FIRST = Arrays.asList("url", "doi"); private static final List DOI_FIRST = Arrays.asList("doi", "url"); - private static final List ARXIV = Arrays.asList("eprint"); + private static final List ARXIV = Collections.singletonList("eprint"); private final BibDatabase database; diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index 908e55c256a6..1bdb359a2be4 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -286,7 +286,7 @@ public void mouseClicked(MouseEvent e) { final List fieldNames = modelColumn.getBibtexFields(); // Open it now. We do this in a thread, so the program won't freeze during the wait. - JabRefExecutorService.INSTANCE.execute((Runnable) () -> { + JabRefExecutorService.INSTANCE.execute(() -> { panel.output(Localization.lang("External viewer called") + '.'); // check for all field names whether a link is present // (is relevant for combinations such as "url/doi") diff --git a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java index 0ffb4404fa0d..614ca0000521 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java +++ b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java @@ -1,6 +1,6 @@ package net.sf.jabref.gui.maintable; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -38,7 +38,7 @@ public String getDisplayName() { }; public static final MainTableColumn RANKING_COLUMN = new MainTableColumn(SpecialFieldsUtils.FIELDNAME_RANKING, - Arrays.asList(SpecialFieldsUtils.FIELDNAME_RANKING), + Collections.singletonList(SpecialFieldsUtils.FIELDNAME_RANKING), new JLabel(SpecialFieldsUtils.FIELDNAME_RANKING)) { @Override @@ -53,7 +53,7 @@ public Object getColumnValue(BibEntry entry) { }; public static final MainTableColumn PRIORITY_COLUMN = new MainTableColumn(SpecialFieldsUtils.FIELDNAME_PRIORITY, - Arrays.asList(SpecialFieldsUtils.FIELDNAME_PRIORITY), + Collections.singletonList(SpecialFieldsUtils.FIELDNAME_PRIORITY), new JLabel(Priority.getInstance().getRepresentingIcon())) { @Override @@ -70,7 +70,7 @@ public Object getColumnValue(BibEntry entry) { }; public static final MainTableColumn READ_STATUS_COLUMN = new MainTableColumn(SpecialFieldsUtils.FIELDNAME_READ, - Arrays.asList(SpecialFieldsUtils.FIELDNAME_READ), + Collections.singletonList(SpecialFieldsUtils.FIELDNAME_READ), new JLabel(ReadStatus.getInstance().getRepresentingIcon())) { @Override @@ -87,20 +87,20 @@ public Object getColumnValue(BibEntry entry) { }; public static final MainTableColumn RELEVANCE_COLUMN = createIconColumn(SpecialFieldsUtils.FIELDNAME_RELEVANCE, - Arrays.asList(SpecialFieldsUtils.FIELDNAME_RELEVANCE), + Collections.singletonList(SpecialFieldsUtils.FIELDNAME_RELEVANCE), new JLabel(Relevance.getInstance().getRepresentingIcon())); public static final MainTableColumn PRINTED_COLUMN = createIconColumn(SpecialFieldsUtils.FIELDNAME_PRINTED, - Arrays.asList(SpecialFieldsUtils.FIELDNAME_PRINTED), + Collections.singletonList(SpecialFieldsUtils.FIELDNAME_PRINTED), new JLabel(Printed.getInstance().getRepresentingIcon())); public static final MainTableColumn QUALITY_COLUMN = createIconColumn(SpecialFieldsUtils.FIELDNAME_QUALITY, - Arrays.asList(SpecialFieldsUtils.FIELDNAME_QUALITY), + Collections.singletonList(SpecialFieldsUtils.FIELDNAME_QUALITY), new JLabel(Quality.getInstance().getRepresentingIcon())); public static final MainTableColumn FILE_COLUMN = new MainTableColumn(Globals.FILE_FIELD, - Arrays.asList(Globals.FILE_FIELD), new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon())) { + Collections.singletonList(Globals.FILE_FIELD), new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon())) { @Override public Object getColumnValue(BibEntry entry) { @@ -167,7 +167,7 @@ public static MainTableColumn createFileIconColumn(String externalFileTypeName) - return new MainTableColumn(externalFileTypeName, Arrays.asList(Globals.FILE_FIELD), new JLabel()) { + return new MainTableColumn(externalFileTypeName, Collections.singletonList(Globals.FILE_FIELD), new JLabel()) { @Override public boolean isFileFilter() { diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java index d6053cf3900e..aa4295ec000b 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java @@ -978,7 +978,7 @@ private void insertFullReferenceAtCursor(XTextCursor cursor, Map listEvent) { preview.setLayout(style.getReferenceFormat("default")); // Update the preview's entry: - SwingUtilities.invokeLater((Runnable) () -> { + SwingUtilities.invokeLater(() -> { preview.update(); preview.scrollRectToVisible(toRect); }); diff --git a/src/main/java/net/sf/jabref/importer/CustomImporter.java b/src/main/java/net/sf/jabref/importer/CustomImporter.java index 9347fa7a0ee9..44394dbb91dc 100644 --- a/src/main/java/net/sf/jabref/importer/CustomImporter.java +++ b/src/main/java/net/sf/jabref/importer/CustomImporter.java @@ -131,7 +131,7 @@ public String toString() { return this.name; } - public ImportFormat getInstance() throws IOException, MalformedURLException, ClassNotFoundException, + public ImportFormat getInstance() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { try (URLClassLoader cl = new URLClassLoader(new URL[] {getBasePathUrl()})) { Class clazz = Class.forName(className, true, cl); diff --git a/src/main/java/net/sf/jabref/importer/ImportFormats.java b/src/main/java/net/sf/jabref/importer/ImportFormats.java index 82fe40312f23..8b713f6a0095 100644 --- a/src/main/java/net/sf/jabref/importer/ImportFormats.java +++ b/src/main/java/net/sf/jabref/importer/ImportFormats.java @@ -17,7 +17,7 @@ import java.awt.event.ActionEvent; import java.io.File; -import java.util.Arrays; +import java.util.Collections; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -124,7 +124,7 @@ public void actionPerformed(ActionEvent e) { return; } ImportMenuItem imi = new ImportMenuItem(frame, openInNew, format); - imi.automatedImport(Arrays.asList(file.getAbsolutePath())); + imi.automatedImport(Collections.singletonList(file.getAbsolutePath())); // Make sure we remember which filter was used, to set the default // for next time: diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index 74b15fc2d385..ab92590d65bb 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -183,7 +183,7 @@ public void openFiles(List filesToOpen, boolean raisePanel) { // locking until the file is loaded. if (!filesToOpen.isEmpty()) { final List theFiles = Collections.unmodifiableList(filesToOpen); - JabRefExecutorService.INSTANCE.execute((Runnable) () -> { + JabRefExecutorService.INSTANCE.execute(() -> { for (File theFile : theFiles) { openTheFile(theFile, raisePanel); } diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java index b4c332bb6ab9..fd347b39b36a 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java @@ -56,7 +56,7 @@ public String format(String text) { if (code == null) { sb.append((char) cpCurrent); } else { - sb.append("{\\" + code + '{' + (char) cpCurrent + "}}"); + sb.append("{\\").append(code).append('{').append((char) cpCurrent).append("}}"); consumed = true; } } else { diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java b/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java index abc5f27210b5..55f3141178dc 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java @@ -41,7 +41,7 @@ public static Set findAllWordsInField(BibDatabase db, String field, Stri Set res = new TreeSet<>(); for (BibEntry be : db.getEntries()) { be.getFieldOptional(field).ifPresent(o -> { - StringTokenizer tok = new StringTokenizer(o.toString(), remove, false); + StringTokenizer tok = new StringTokenizer(o, remove, false); while (tok.hasMoreTokens()) { res.add(net.sf.jabref.model.entry.EntryUtil.capitalizeFirst(tok.nextToken().trim())); } diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java index 70a5d9f5fbf4..c2678b9b4073 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java @@ -19,6 +19,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -690,11 +691,11 @@ public static List> parseMethodsCalls(String calls) { } } else { // Incorrectly terminated open brace - result.add(Arrays.asList(method)); + result.add(Collections.singletonList(method)); } } else { String method = calls.substring(start, i); - result.add(Arrays.asList(method)); + result.add(Collections.singletonList(method)); } } i++; diff --git a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java index 319ba7ded43e..9108a85e0090 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java @@ -17,7 +17,7 @@ import java.io.File; import java.io.IOException; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -76,7 +76,7 @@ public String format(String field) { // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: if (Globals.prefs.fileDirForDatabase == null) { - dirs = Arrays.asList(Globals.prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); + dirs = Collections.singletonList(Globals.prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); } else { dirs = Globals.prefs.fileDirForDatabase; } diff --git a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java index 94d0e212e804..426c2ecd0916 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java @@ -18,7 +18,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -171,7 +171,7 @@ public String format(String field) { // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: if (Globals.prefs.fileDirForDatabase == null) { - dirs = Arrays.asList(Globals.prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); + dirs = Collections.singletonList(Globals.prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); } else { dirs = Globals.prefs.fileDirForDatabase; } diff --git a/src/main/java/net/sf/jabref/logic/search/SearchQueryHighlightObservable.java b/src/main/java/net/sf/jabref/logic/search/SearchQueryHighlightObservable.java index 2bee5c04983e..0deafe75b1fe 100644 --- a/src/main/java/net/sf/jabref/logic/search/SearchQueryHighlightObservable.java +++ b/src/main/java/net/sf/jabref/logic/search/SearchQueryHighlightObservable.java @@ -1,7 +1,7 @@ package net.sf.jabref.logic.search; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -73,7 +73,7 @@ public void fireSearchlistenerEvent(SearchQuery searchQuery) { if (searchQuery.isGrammarBasedSearch()) { pattern = Optional.empty(); } else if (searchQuery.isRegularExpression()) { - pattern = getPatternForWords(Arrays.asList(searchQuery.getQuery()), true, searchQuery.isCaseSensitive()); + pattern = getPatternForWords(Collections.singletonList(searchQuery.getQuery()), true, searchQuery.isCaseSensitive()); } else { pattern = getPatternForWords(getSearchwords(searchQuery.getQuery()), searchQuery.isRegularExpression(), searchQuery.isCaseSensitive()); } diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index fc586b177cdd..a3c1183c5322 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -146,7 +146,7 @@ public static List readXMP(File file) throws IOException { } public static PDDocument loadWithAutomaticDecryption(InputStream inputStream) - throws IOException, EncryptedPdfsNotSupportedException { + throws IOException { PDDocument doc = PDDocument.load(inputStream); if (doc.isEncrypted()) { // try the empty string as user password @@ -1166,8 +1166,7 @@ private static void usage() { * @throws TransformerException * If the given BibEntry is malformed. */ - public static void main(String[] args) throws IOException, - TransformerException { + public static void main(String[] args) throws IOException, TransformerException { // Don't forget to initialize the preferences if (Globals.prefs == null) { From e5ac61c6ddd7f33bd394d68f2b5d2c724d6cc41b Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:30:26 +0200 Subject: [PATCH 034/268] More refactorings --- .../sf/jabref/bibtex/BibtexSingleField.java | 2 +- .../bibtex/comparator/FieldComparator.java | 2 +- .../net/sf/jabref/logic/net/URLDownload.java | 2 +- .../jabref/sql/exporter/DatabaseExporter.java | 56 +++++++++---------- src/main/resources/l10n/JabRef_de.properties | 2 +- 5 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/main/java/net/sf/jabref/bibtex/BibtexSingleField.java b/src/main/java/net/sf/jabref/bibtex/BibtexSingleField.java index bb92d9cc620e..82374f140cc9 100644 --- a/src/main/java/net/sf/jabref/bibtex/BibtexSingleField.java +++ b/src/main/java/net/sf/jabref/bibtex/BibtexSingleField.java @@ -25,7 +25,7 @@ private enum Flag { STANDARD, PRIVATE, DISPLAYABLE, - WRITEABLE; + WRITEABLE } diff --git a/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparator.java b/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparator.java index 1b67929aca2c..ade5f192e0f2 100644 --- a/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparator.java +++ b/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparator.java @@ -57,7 +57,7 @@ private static Collator getCollator() { } enum FieldType { - NAME, TYPE, YEAR, MONTH, OTHER; + NAME, TYPE, YEAR, MONTH, OTHER } private final String[] field; diff --git a/src/main/java/net/sf/jabref/logic/net/URLDownload.java b/src/main/java/net/sf/jabref/logic/net/URLDownload.java index 1584b014f101..b0d3c4f252eb 100644 --- a/src/main/java/net/sf/jabref/logic/net/URLDownload.java +++ b/src/main/java/net/sf/jabref/logic/net/URLDownload.java @@ -123,7 +123,7 @@ private URLConnection openConnection() throws IOException { } if (!postData.isEmpty()) { connection.setDoOutput(true); - try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream());) { + try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) { wr.writeBytes(postData); } diff --git a/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java b/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java index 2d74b4f04bc8..24cc5990faa6 100644 --- a/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java +++ b/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java @@ -385,37 +385,33 @@ public void createTables(Connection out) throws SQLException { public void exportDatabaseToDBMS(final BibDatabaseContext databaseContext, List entriesToExport, DBStrings databaseStrings, JabRefFrame frame) throws Exception { String dbName; - Connection conn = null; boolean redisplay = false; - try { - conn = this.connectToDB(databaseStrings); - createTables(conn); - Vector> matrix = createExistentDBNamesMatrix(databaseStrings); - DBImportExportDialog dialogo = new DBImportExportDialog(frame, matrix, - DBImportExportDialog.DialogType.EXPORTER); - if (dialogo.removeAction) { - dbName = getDBName(matrix, databaseStrings, frame, dialogo); - DatabaseUtil.removeDB(dialogo, dbName, conn, databaseContext); - redisplay = true; - } else if (dialogo.hasDBSelected) { - dbName = getDBName(matrix, databaseStrings, frame, dialogo); - performExport(databaseContext, entriesToExport, conn, dbName); - } - if (!conn.getAutoCommit()) { - conn.commit(); - conn.setAutoCommit(true); - } - if (redisplay) { - exportDatabaseToDBMS(databaseContext, entriesToExport, databaseStrings, frame); - } - } catch (SQLException ex) { - if ((conn != null) && !conn.getAutoCommit()) { - conn.rollback(); - } - throw ex; - } finally { - if (conn != null) { - conn.close(); + try(Connection conn = this.connectToDB(databaseStrings)) { + try { + createTables(conn); + Vector> matrix = createExistentDBNamesMatrix(databaseStrings); + DBImportExportDialog dialogo = new DBImportExportDialog(frame, matrix, + DBImportExportDialog.DialogType.EXPORTER); + if (dialogo.removeAction) { + dbName = getDBName(matrix, databaseStrings, frame, dialogo); + DatabaseUtil.removeDB(dialogo, dbName, conn, databaseContext); + redisplay = true; + } else if (dialogo.hasDBSelected) { + dbName = getDBName(matrix, databaseStrings, frame, dialogo); + performExport(databaseContext, entriesToExport, conn, dbName); + } + if (!conn.getAutoCommit()) { + conn.commit(); + conn.setAutoCommit(true); + } + if (redisplay) { + exportDatabaseToDBMS(databaseContext, entriesToExport, databaseStrings, frame); + } + } catch (SQLException ex) { + if ((conn != null) && !conn.getAutoCommit()) { + conn.rollback(); + } + throw ex; } } } diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index acaeb0fff215..849019fcea12 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2263,7 +2263,7 @@ You_have_entered_an_invalid_or_already_existent_DB_name.=Sie_haben_einen_ungült Disable_highlight_groups_matching_entries=Keine_Gruppen_hervorheben -Run_field_formatter\:=Führe_Feldformatierer_aus:\ +Run_field_formatter\:=Führe_Feldformatierer_aus\: Adds_{}_brackets_around_acronyms,_month_names_and_countries_to_preserve_their_case.=Fügt_{}-Klammern_um_Akronyme,_Monatsnamen_und_Ländernamen_ein,_um_Groß-/Kleinschreibung_beizubehalten. Converts_units_to_LaTeX_formatting.=Konvertiert_Einheiten_in_LaTeX-Code. From 9442498e09ce6ca454ebfbd5d83a524762231e50 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:49:12 +0200 Subject: [PATCH 035/268] Fix #1313 --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/preftabs/FileTab.java | 6 ------ src/main/resources/l10n/JabRef_da.properties | 1 - src/main/resources/l10n/JabRef_de.properties | 1 - src/main/resources/l10n/JabRef_en.properties | 1 - src/main/resources/l10n/JabRef_es.properties | 1 - src/main/resources/l10n/JabRef_fa.properties | 1 - src/main/resources/l10n/JabRef_fr.properties | 1 - src/main/resources/l10n/JabRef_in.properties | 1 - src/main/resources/l10n/JabRef_it.properties | 1 - src/main/resources/l10n/JabRef_ja.properties | 1 - src/main/resources/l10n/JabRef_nl.properties | 1 - src/main/resources/l10n/JabRef_no.properties | 2 -- src/main/resources/l10n/JabRef_pt_BR.properties | 1 - src/main/resources/l10n/JabRef_ru.properties | 1 - src/main/resources/l10n/JabRef_sv.properties | 1 - src/main/resources/l10n/JabRef_tr.properties | 1 - src/main/resources/l10n/JabRef_vi.properties | 1 - src/main/resources/l10n/JabRef_zh.properties | 1 - 19 files changed, 1 insertion(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b200af7811..17b06fea0420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed: Selecting invalid jstyle causes NPE and prevents opening of style selection dialog - Fixed: Move linked files to default directory works again - Fixed [#1327](https://github.com/JabRef/jabref/issues/1327): PDF cleanup changes order of linked pdfs +- Fixed [#1313](https://github.com/JabRef/jabref/issues/1313): Remove UI for a configuration option which was no longer available ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index db41d85c342d..3c4aa2f30ee2 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -67,7 +67,6 @@ class FileTab extends JPanel implements PrefsTab { private boolean origAutoSaveSetting; private final JTextField fileDir; - private final JCheckBox bibLocationAsFileDir; private final JCheckBox bibLocAsPrimaryDir; private final JCheckBox runAutoFileSearch; private final JCheckBox allowFileAutoOpenBrowse; @@ -82,11 +81,9 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { this.frame = frame; fileDir = new JTextField(25); - bibLocationAsFileDir = new JCheckBox(Localization.lang("Allow file links relative to each bib file's location")); bibLocAsPrimaryDir = new JCheckBox(Localization.lang("Use the bib file location as primary file directory")); bibLocAsPrimaryDir.setToolTipText(Localization.lang("When downloading files, or moving linked files to the " + "file directory, prefer the bib file location rather than the file directory set above")); - bibLocationAsFileDir.addChangeListener(e -> bibLocAsPrimaryDir.setEnabled(bibLocationAsFileDir.isSelected())); runAutoFileSearch = new JCheckBox(Localization.lang("When opening file link, search for matching file if no link is defined")); allowFileAutoOpenBrowse = new JCheckBox(Localization.lang("Automatically open browse dialog when creating new file link")); regExpTextField = new JTextField(25); @@ -166,8 +163,6 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { BrowseAction browse = BrowseAction.buildForDir(this.frame, fileDir); builder.append(new JButton(browse)); builder.nextLine(); - builder.append(bibLocationAsFileDir, 3); - builder.nextLine(); builder.append(bibLocAsPrimaryDir, 3); builder.nextLine(); builder.append(matchStartsWithKey, 3); @@ -212,7 +207,6 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { public void setValues() { fileDir.setText(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); bibLocAsPrimaryDir.setSelected(prefs.getBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR)); - bibLocAsPrimaryDir.setEnabled(bibLocationAsFileDir.isSelected()); runAutoFileSearch.setSelected(prefs.getBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH)); allowFileAutoOpenBrowse.setSelected(prefs.getBoolean(JabRefPreferences.ALLOW_FILE_AUTO_OPEN_BROWSE)); regExpTextField.setText(prefs.get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY)); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 10965248694a..f0b1fccfb52f 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1076,7 +1076,6 @@ Could_not_open_%0=Kunne_ikke_åbne_%0 Unknown_import_format=Ukendt_importformat Web_search=Websøgning -Allow_file_links_relative_to_each_bib_file's_location=Tillad_fillinks_relativt_fra_biblioteket_hvor_hver_bib-fil_ligger Style_selection=Valg_af_stil No_valid_style_file_defined=Ingen_gyldig_stilfil_defineret diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 849019fcea12..4c9477791700 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1784,7 +1784,6 @@ Could_not_open_%0=%0_konnte_nicht_geöffnet_werden Unknown_import_format=Unbekanntes_Import-Format Web_search=Internetrecherche -Allow_file_links_relative_to_each_bib_file's_location=Dateilinks_relativ_zum_Pfad_der_bib-Datei_erlauben Style_selection=Stil-Auswahl No_valid_style_file_defined=Keine_gültige_Stildatei_angegeben diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 251d6d88235c..8b7424728447 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1686,7 +1686,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Could_not_open_%0 Unknown_import_format=Unknown_import_format Web_search=Web_search -Allow_file_links_relative_to_each_bib_file's_location=Allow_file_links_relative_to_each_bib_file's_location Style_selection=Style_selection No_valid_style_file_defined=No_valid_style_file_defined Choose_pattern=Choose_pattern diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index eeaee188abf0..c7f885594c77 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -993,7 +993,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=No_se_puede_abrir_%0 Unknown_import_format=Formato_de_importación_desconocido Web_search=Búsqueda_web -Allow_file_links_relative_to_each_bib_file's_location=Permitir_enlaces_a_archivos_relativos_a_la_ubicación_de_cada_archivo_bib Style_selection=Selección_de_estilo No_valid_style_file_defined=No_se_ha_definido_un_archivo_de_estilo_válido Choose_pattern=Escoger_patrón diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index bbf01f8166d0..67d94b1286ef 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1738,7 +1738,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= -Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= Choose_pattern= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 4064e50360ef..b560f0577201 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1013,7 +1013,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0_n'a_pas_pu_être_ouvert Unknown_import_format=Format_d'importation_inconnu Web_search=Recherche_web -Allow_file_links_relative_to_each_bib_file's_location=Autoriser_les_liens_de_fichier_relatif_à_chaque_répertoire_de_fichier_BibTeX Style_selection=Sélection_du_style No_valid_style_file_defined=Aucun_style_de_fichier_valide_n'est_défini diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 0643fd1cd9bf..b6bc934a8c62 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -994,7 +994,6 @@ Could_not_open_%0=Tidak_bisa_membuka_%0 Unknown_import_format=Format_impor_tidak_dikenal Web_search=Pencarian_Web -Allow_file_links_relative_to_each_bib_file's_location=Membolehkan_lokasi_tautan_berkas_relatif_untuk_tiap-tiap_berkas_bib Style_selection=Pilihan_gaya No_valid_style_file_defined=(gaya_yang_sah_tidak_ditemukan) diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index dec53c680d4a..0dd7106f9bfe 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1091,7 +1091,6 @@ Could_not_open_%0=Impossiblie_aprire_%0 Unknown_import_format=Formato_di_importazione_sconosciuto Web_search=Ricerca_sul_Web -Allow_file_links_relative_to_each_bib_file's_location=Consenti_il_collegamento_dei_file_relativo_alla_posizione_di_ciascun_file_BibTeX Style_selection=Selezione_dello_stile No_valid_style_file_defined=Nessun_file_di_stile_valido_definito diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 08817721fbda..afc8680aa3b1 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1767,7 +1767,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0を開くことができませんでした Unknown_import_format=未知の読み込み型です Web_search=ウェブ検索 -Allow_file_links_relative_to_each_bib_file's_location=各bibファイルの場所から相対パスでファイルをリンクすることを許可 Style_selection=様式の選択 No_valid_style_file_defined=有効な様式ファイルが定義されていません diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index d770ef423058..15aa93f20a80 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1769,7 +1769,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= -Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 8cad5b7637d2..4770b8737b29 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2144,8 +2144,6 @@ Web_search=Webs\u00f8k -Allow_file_links_relative_to_each_bib_file's_location=Tillat_fillenker_relativt_fra_katalogen_hvor_hver_bib-fil_ligger - Style_selection=Valg_av_stil diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 56839c7d3f7e..9a173f8cf9d4 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -992,7 +992,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Não_foi_possível_abrir_%0 Unknown_import_format=Formato_de_importação_desconhecido Web_search=Pesquisa_na_Web -Allow_file_links_relative_to_each_bib_file's_location=Permitir_links_de_arquivos_relativos_ao_local_do_arquivo_.bib Style_selection=Seleção_de_estilo No_valid_style_file_defined=Nenhum_estilo_válido_definido Choose_pattern=Escolher_modelo diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index e0fd33207628..b2966a16ef78 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1735,7 +1735,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Не_удалось_открыть_%0 Unknown_import_format=Неизвестный_формат_импорта Web_search=Веб-поиск -Allow_file_links_relative_to_each_bib_file's_location=Разрешить_относительные_ссылки_для_расположения_каждого_файла_BibTeX Style_selection=Выбор_стиля No_valid_style_file_defined=Не_определен_допустимый_файл_стиля Choose_pattern=Выбор_шаблона diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index b351a03f2ae0..9c31f8f2254b 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -64,7 +64,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?= All_fields=Alla_fält All_key_bindings_will_be_reset_to_their_defaults.=Alla_tangentbordsbindingar_kommer_att_återställas_till_standardvärden. All_subgroups_(recursively)=Alla_undergrupper_(rekursivt) -Allow_file_links_relative_to_each_bib_file's_location= Allow_overwriting_existing_links.=Tillåt_att_befintliga_länkar_skrivs_över. Always_add_letter_(a,_b,_...)_to_generated_keys=Lägg_alltid_till_en_bokstav_(a,_b_...)_på_genererade_nycklar Always_reformat_.bib_file_on_save_and_export=Formattera_allid_om_.bib-filen_vid_när_den_sparas_eller_exporteras diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index ed98752ddde1..df52e768256e 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1012,7 +1012,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0_açılamıyor Unknown_import_format=Bilinmeyen_içe_aktarım_biçimi Web_search=Ağ_araması -Allow_file_links_relative_to_each_bib_file's_location=Her_bib_dosyasının_konumuna_göre_dosya_bağlantılarına_izin_ver Style_selection=Stil_seçimi No_valid_style_file_defined=Geçerli_stil_dosyası_tanımlanmadı diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index bf86774bc1b5..9574627595b4 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1765,7 +1765,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= -Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 1f2cfeb6a282..0afe429bc47c 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1067,7 +1067,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=无法打开_%0 Unknown_import_format=未知的导入格式 Web_search=网页搜索 -Allow_file_links_relative_to_each_bib_file's_location=允许文件链接使用基于_.bib_文件位置的相对路径 Style_selection=引用样式选择 No_valid_style_file_defined=没有找到合法的_style_文件 From 4ece35bb4c886ad4c05c38dd8392f681abe15235 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 9 May 2016 22:59:32 +0200 Subject: [PATCH 036/268] Revert "Fix #1313" This reverts commit 9442498e09ce6ca454ebfbd5d83a524762231e50. --- CHANGELOG.md | 1 - src/main/java/net/sf/jabref/gui/preftabs/FileTab.java | 6 ++++++ src/main/resources/l10n/JabRef_da.properties | 1 + src/main/resources/l10n/JabRef_de.properties | 1 + src/main/resources/l10n/JabRef_en.properties | 1 + src/main/resources/l10n/JabRef_es.properties | 1 + src/main/resources/l10n/JabRef_fa.properties | 1 + src/main/resources/l10n/JabRef_fr.properties | 1 + src/main/resources/l10n/JabRef_in.properties | 1 + src/main/resources/l10n/JabRef_it.properties | 1 + src/main/resources/l10n/JabRef_ja.properties | 1 + src/main/resources/l10n/JabRef_nl.properties | 1 + src/main/resources/l10n/JabRef_no.properties | 2 ++ src/main/resources/l10n/JabRef_pt_BR.properties | 1 + src/main/resources/l10n/JabRef_ru.properties | 1 + src/main/resources/l10n/JabRef_sv.properties | 1 + src/main/resources/l10n/JabRef_tr.properties | 1 + src/main/resources/l10n/JabRef_vi.properties | 1 + src/main/resources/l10n/JabRef_zh.properties | 1 + 19 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17b06fea0420..77b200af7811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,6 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed: Selecting invalid jstyle causes NPE and prevents opening of style selection dialog - Fixed: Move linked files to default directory works again - Fixed [#1327](https://github.com/JabRef/jabref/issues/1327): PDF cleanup changes order of linked pdfs -- Fixed [#1313](https://github.com/JabRef/jabref/issues/1313): Remove UI for a configuration option which was no longer available ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index 3c4aa2f30ee2..db41d85c342d 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -67,6 +67,7 @@ class FileTab extends JPanel implements PrefsTab { private boolean origAutoSaveSetting; private final JTextField fileDir; + private final JCheckBox bibLocationAsFileDir; private final JCheckBox bibLocAsPrimaryDir; private final JCheckBox runAutoFileSearch; private final JCheckBox allowFileAutoOpenBrowse; @@ -81,9 +82,11 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { this.frame = frame; fileDir = new JTextField(25); + bibLocationAsFileDir = new JCheckBox(Localization.lang("Allow file links relative to each bib file's location")); bibLocAsPrimaryDir = new JCheckBox(Localization.lang("Use the bib file location as primary file directory")); bibLocAsPrimaryDir.setToolTipText(Localization.lang("When downloading files, or moving linked files to the " + "file directory, prefer the bib file location rather than the file directory set above")); + bibLocationAsFileDir.addChangeListener(e -> bibLocAsPrimaryDir.setEnabled(bibLocationAsFileDir.isSelected())); runAutoFileSearch = new JCheckBox(Localization.lang("When opening file link, search for matching file if no link is defined")); allowFileAutoOpenBrowse = new JCheckBox(Localization.lang("Automatically open browse dialog when creating new file link")); regExpTextField = new JTextField(25); @@ -163,6 +166,8 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { BrowseAction browse = BrowseAction.buildForDir(this.frame, fileDir); builder.append(new JButton(browse)); builder.nextLine(); + builder.append(bibLocationAsFileDir, 3); + builder.nextLine(); builder.append(bibLocAsPrimaryDir, 3); builder.nextLine(); builder.append(matchStartsWithKey, 3); @@ -207,6 +212,7 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { public void setValues() { fileDir.setText(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); bibLocAsPrimaryDir.setSelected(prefs.getBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR)); + bibLocAsPrimaryDir.setEnabled(bibLocationAsFileDir.isSelected()); runAutoFileSearch.setSelected(prefs.getBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH)); allowFileAutoOpenBrowse.setSelected(prefs.getBoolean(JabRefPreferences.ALLOW_FILE_AUTO_OPEN_BROWSE)); regExpTextField.setText(prefs.get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY)); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index f0b1fccfb52f..10965248694a 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1076,6 +1076,7 @@ Could_not_open_%0=Kunne_ikke_åbne_%0 Unknown_import_format=Ukendt_importformat Web_search=Websøgning +Allow_file_links_relative_to_each_bib_file's_location=Tillad_fillinks_relativt_fra_biblioteket_hvor_hver_bib-fil_ligger Style_selection=Valg_af_stil No_valid_style_file_defined=Ingen_gyldig_stilfil_defineret diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 4c9477791700..849019fcea12 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1784,6 +1784,7 @@ Could_not_open_%0=%0_konnte_nicht_geöffnet_werden Unknown_import_format=Unbekanntes_Import-Format Web_search=Internetrecherche +Allow_file_links_relative_to_each_bib_file's_location=Dateilinks_relativ_zum_Pfad_der_bib-Datei_erlauben Style_selection=Stil-Auswahl No_valid_style_file_defined=Keine_gültige_Stildatei_angegeben diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 8b7424728447..251d6d88235c 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1686,6 +1686,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Could_not_open_%0 Unknown_import_format=Unknown_import_format Web_search=Web_search +Allow_file_links_relative_to_each_bib_file's_location=Allow_file_links_relative_to_each_bib_file's_location Style_selection=Style_selection No_valid_style_file_defined=No_valid_style_file_defined Choose_pattern=Choose_pattern diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index c7f885594c77..eeaee188abf0 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -993,6 +993,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=No_se_puede_abrir_%0 Unknown_import_format=Formato_de_importación_desconocido Web_search=Búsqueda_web +Allow_file_links_relative_to_each_bib_file's_location=Permitir_enlaces_a_archivos_relativos_a_la_ubicación_de_cada_archivo_bib Style_selection=Selección_de_estilo No_valid_style_file_defined=No_se_ha_definido_un_archivo_de_estilo_válido Choose_pattern=Escoger_patrón diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 67d94b1286ef..bbf01f8166d0 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1738,6 +1738,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= +Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= Choose_pattern= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index b560f0577201..4064e50360ef 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1013,6 +1013,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0_n'a_pas_pu_être_ouvert Unknown_import_format=Format_d'importation_inconnu Web_search=Recherche_web +Allow_file_links_relative_to_each_bib_file's_location=Autoriser_les_liens_de_fichier_relatif_à_chaque_répertoire_de_fichier_BibTeX Style_selection=Sélection_du_style No_valid_style_file_defined=Aucun_style_de_fichier_valide_n'est_défini diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index b6bc934a8c62..0643fd1cd9bf 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -994,6 +994,7 @@ Could_not_open_%0=Tidak_bisa_membuka_%0 Unknown_import_format=Format_impor_tidak_dikenal Web_search=Pencarian_Web +Allow_file_links_relative_to_each_bib_file's_location=Membolehkan_lokasi_tautan_berkas_relatif_untuk_tiap-tiap_berkas_bib Style_selection=Pilihan_gaya No_valid_style_file_defined=(gaya_yang_sah_tidak_ditemukan) diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 0dd7106f9bfe..dec53c680d4a 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1091,6 +1091,7 @@ Could_not_open_%0=Impossiblie_aprire_%0 Unknown_import_format=Formato_di_importazione_sconosciuto Web_search=Ricerca_sul_Web +Allow_file_links_relative_to_each_bib_file's_location=Consenti_il_collegamento_dei_file_relativo_alla_posizione_di_ciascun_file_BibTeX Style_selection=Selezione_dello_stile No_valid_style_file_defined=Nessun_file_di_stile_valido_definito diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index afc8680aa3b1..08817721fbda 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1767,6 +1767,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0を開くことができませんでした Unknown_import_format=未知の読み込み型です Web_search=ウェブ検索 +Allow_file_links_relative_to_each_bib_file's_location=各bibファイルの場所から相対パスでファイルをリンクすることを許可 Style_selection=様式の選択 No_valid_style_file_defined=有効な様式ファイルが定義されていません diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 15aa93f20a80..d770ef423058 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1769,6 +1769,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= +Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 4770b8737b29..8cad5b7637d2 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2144,6 +2144,8 @@ Web_search=Webs\u00f8k +Allow_file_links_relative_to_each_bib_file's_location=Tillat_fillenker_relativt_fra_katalogen_hvor_hver_bib-fil_ligger + Style_selection=Valg_av_stil diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 9a173f8cf9d4..56839c7d3f7e 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -992,6 +992,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Não_foi_possível_abrir_%0 Unknown_import_format=Formato_de_importação_desconhecido Web_search=Pesquisa_na_Web +Allow_file_links_relative_to_each_bib_file's_location=Permitir_links_de_arquivos_relativos_ao_local_do_arquivo_.bib Style_selection=Seleção_de_estilo No_valid_style_file_defined=Nenhum_estilo_válido_definido Choose_pattern=Escolher_modelo diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index b2966a16ef78..e0fd33207628 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1735,6 +1735,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Не_удалось_открыть_%0 Unknown_import_format=Неизвестный_формат_импорта Web_search=Веб-поиск +Allow_file_links_relative_to_each_bib_file's_location=Разрешить_относительные_ссылки_для_расположения_каждого_файла_BibTeX Style_selection=Выбор_стиля No_valid_style_file_defined=Не_определен_допустимый_файл_стиля Choose_pattern=Выбор_шаблона diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 9c31f8f2254b..b351a03f2ae0 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -64,6 +64,7 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?= All_fields=Alla_fält All_key_bindings_will_be_reset_to_their_defaults.=Alla_tangentbordsbindingar_kommer_att_återställas_till_standardvärden. All_subgroups_(recursively)=Alla_undergrupper_(rekursivt) +Allow_file_links_relative_to_each_bib_file's_location= Allow_overwriting_existing_links.=Tillåt_att_befintliga_länkar_skrivs_över. Always_add_letter_(a,_b,_...)_to_generated_keys=Lägg_alltid_till_en_bokstav_(a,_b_...)_på_genererade_nycklar Always_reformat_.bib_file_on_save_and_export=Formattera_allid_om_.bib-filen_vid_när_den_sparas_eller_exporteras diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index df52e768256e..ed98752ddde1 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1012,6 +1012,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0_açılamıyor Unknown_import_format=Bilinmeyen_içe_aktarım_biçimi Web_search=Ağ_araması +Allow_file_links_relative_to_each_bib_file's_location=Her_bib_dosyasının_konumuna_göre_dosya_bağlantılarına_izin_ver Style_selection=Stil_seçimi No_valid_style_file_defined=Geçerli_stil_dosyası_tanımlanmadı diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 9574627595b4..bf86774bc1b5 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1765,6 +1765,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= +Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 0afe429bc47c..1f2cfeb6a282 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1067,6 +1067,7 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=无法打开_%0 Unknown_import_format=未知的导入格式 Web_search=网页搜索 +Allow_file_links_relative_to_each_bib_file's_location=允许文件链接使用基于_.bib_文件位置的相对路径 Style_selection=引用样式选择 No_valid_style_file_defined=没有找到合法的_style_文件 From dd96a7ba6bc5f99d247d9a3f31e6fd13e98fa44b Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 10 May 2016 09:10:20 +0200 Subject: [PATCH 037/268] Fix #1313: Remove UI as the checkbox is no longer backed by a config option (#1369) --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/preftabs/FileTab.java | 6 ------ src/main/resources/l10n/JabRef_da.properties | 1 - src/main/resources/l10n/JabRef_de.properties | 1 - src/main/resources/l10n/JabRef_en.properties | 1 - src/main/resources/l10n/JabRef_es.properties | 1 - src/main/resources/l10n/JabRef_fa.properties | 1 - src/main/resources/l10n/JabRef_fr.properties | 1 - src/main/resources/l10n/JabRef_in.properties | 1 - src/main/resources/l10n/JabRef_it.properties | 1 - src/main/resources/l10n/JabRef_ja.properties | 1 - src/main/resources/l10n/JabRef_nl.properties | 1 - src/main/resources/l10n/JabRef_no.properties | 2 -- src/main/resources/l10n/JabRef_pt_BR.properties | 1 - src/main/resources/l10n/JabRef_ru.properties | 1 - src/main/resources/l10n/JabRef_sv.properties | 1 - src/main/resources/l10n/JabRef_tr.properties | 1 - src/main/resources/l10n/JabRef_vi.properties | 1 - src/main/resources/l10n/JabRef_zh.properties | 1 - 19 files changed, 1 insertion(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b200af7811..17b06fea0420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed: Selecting invalid jstyle causes NPE and prevents opening of style selection dialog - Fixed: Move linked files to default directory works again - Fixed [#1327](https://github.com/JabRef/jabref/issues/1327): PDF cleanup changes order of linked pdfs +- Fixed [#1313](https://github.com/JabRef/jabref/issues/1313): Remove UI for a configuration option which was no longer available ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index db41d85c342d..3c4aa2f30ee2 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -67,7 +67,6 @@ class FileTab extends JPanel implements PrefsTab { private boolean origAutoSaveSetting; private final JTextField fileDir; - private final JCheckBox bibLocationAsFileDir; private final JCheckBox bibLocAsPrimaryDir; private final JCheckBox runAutoFileSearch; private final JCheckBox allowFileAutoOpenBrowse; @@ -82,11 +81,9 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { this.frame = frame; fileDir = new JTextField(25); - bibLocationAsFileDir = new JCheckBox(Localization.lang("Allow file links relative to each bib file's location")); bibLocAsPrimaryDir = new JCheckBox(Localization.lang("Use the bib file location as primary file directory")); bibLocAsPrimaryDir.setToolTipText(Localization.lang("When downloading files, or moving linked files to the " + "file directory, prefer the bib file location rather than the file directory set above")); - bibLocationAsFileDir.addChangeListener(e -> bibLocAsPrimaryDir.setEnabled(bibLocationAsFileDir.isSelected())); runAutoFileSearch = new JCheckBox(Localization.lang("When opening file link, search for matching file if no link is defined")); allowFileAutoOpenBrowse = new JCheckBox(Localization.lang("Automatically open browse dialog when creating new file link")); regExpTextField = new JTextField(25); @@ -166,8 +163,6 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { BrowseAction browse = BrowseAction.buildForDir(this.frame, fileDir); builder.append(new JButton(browse)); builder.nextLine(); - builder.append(bibLocationAsFileDir, 3); - builder.nextLine(); builder.append(bibLocAsPrimaryDir, 3); builder.nextLine(); builder.append(matchStartsWithKey, 3); @@ -212,7 +207,6 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { public void setValues() { fileDir.setText(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); bibLocAsPrimaryDir.setSelected(prefs.getBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR)); - bibLocAsPrimaryDir.setEnabled(bibLocationAsFileDir.isSelected()); runAutoFileSearch.setSelected(prefs.getBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH)); allowFileAutoOpenBrowse.setSelected(prefs.getBoolean(JabRefPreferences.ALLOW_FILE_AUTO_OPEN_BROWSE)); regExpTextField.setText(prefs.get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY)); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 10965248694a..f0b1fccfb52f 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1076,7 +1076,6 @@ Could_not_open_%0=Kunne_ikke_åbne_%0 Unknown_import_format=Ukendt_importformat Web_search=Websøgning -Allow_file_links_relative_to_each_bib_file's_location=Tillad_fillinks_relativt_fra_biblioteket_hvor_hver_bib-fil_ligger Style_selection=Valg_af_stil No_valid_style_file_defined=Ingen_gyldig_stilfil_defineret diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 849019fcea12..4c9477791700 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1784,7 +1784,6 @@ Could_not_open_%0=%0_konnte_nicht_geöffnet_werden Unknown_import_format=Unbekanntes_Import-Format Web_search=Internetrecherche -Allow_file_links_relative_to_each_bib_file's_location=Dateilinks_relativ_zum_Pfad_der_bib-Datei_erlauben Style_selection=Stil-Auswahl No_valid_style_file_defined=Keine_gültige_Stildatei_angegeben diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 251d6d88235c..8b7424728447 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1686,7 +1686,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Could_not_open_%0 Unknown_import_format=Unknown_import_format Web_search=Web_search -Allow_file_links_relative_to_each_bib_file's_location=Allow_file_links_relative_to_each_bib_file's_location Style_selection=Style_selection No_valid_style_file_defined=No_valid_style_file_defined Choose_pattern=Choose_pattern diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index eeaee188abf0..c7f885594c77 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -993,7 +993,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=No_se_puede_abrir_%0 Unknown_import_format=Formato_de_importación_desconocido Web_search=Búsqueda_web -Allow_file_links_relative_to_each_bib_file's_location=Permitir_enlaces_a_archivos_relativos_a_la_ubicación_de_cada_archivo_bib Style_selection=Selección_de_estilo No_valid_style_file_defined=No_se_ha_definido_un_archivo_de_estilo_válido Choose_pattern=Escoger_patrón diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index bbf01f8166d0..67d94b1286ef 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1738,7 +1738,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= -Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= Choose_pattern= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 4064e50360ef..b560f0577201 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1013,7 +1013,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0_n'a_pas_pu_être_ouvert Unknown_import_format=Format_d'importation_inconnu Web_search=Recherche_web -Allow_file_links_relative_to_each_bib_file's_location=Autoriser_les_liens_de_fichier_relatif_à_chaque_répertoire_de_fichier_BibTeX Style_selection=Sélection_du_style No_valid_style_file_defined=Aucun_style_de_fichier_valide_n'est_défini diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 0643fd1cd9bf..b6bc934a8c62 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -994,7 +994,6 @@ Could_not_open_%0=Tidak_bisa_membuka_%0 Unknown_import_format=Format_impor_tidak_dikenal Web_search=Pencarian_Web -Allow_file_links_relative_to_each_bib_file's_location=Membolehkan_lokasi_tautan_berkas_relatif_untuk_tiap-tiap_berkas_bib Style_selection=Pilihan_gaya No_valid_style_file_defined=(gaya_yang_sah_tidak_ditemukan) diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index dec53c680d4a..0dd7106f9bfe 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1091,7 +1091,6 @@ Could_not_open_%0=Impossiblie_aprire_%0 Unknown_import_format=Formato_di_importazione_sconosciuto Web_search=Ricerca_sul_Web -Allow_file_links_relative_to_each_bib_file's_location=Consenti_il_collegamento_dei_file_relativo_alla_posizione_di_ciascun_file_BibTeX Style_selection=Selezione_dello_stile No_valid_style_file_defined=Nessun_file_di_stile_valido_definito diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 08817721fbda..afc8680aa3b1 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1767,7 +1767,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0を開くことができませんでした Unknown_import_format=未知の読み込み型です Web_search=ウェブ検索 -Allow_file_links_relative_to_each_bib_file's_location=各bibファイルの場所から相対パスでファイルをリンクすることを許可 Style_selection=様式の選択 No_valid_style_file_defined=有効な様式ファイルが定義されていません diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index d770ef423058..15aa93f20a80 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1769,7 +1769,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= -Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 8cad5b7637d2..4770b8737b29 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2144,8 +2144,6 @@ Web_search=Webs\u00f8k -Allow_file_links_relative_to_each_bib_file's_location=Tillat_fillenker_relativt_fra_katalogen_hvor_hver_bib-fil_ligger - Style_selection=Valg_av_stil diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 56839c7d3f7e..9a173f8cf9d4 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -992,7 +992,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Não_foi_possível_abrir_%0 Unknown_import_format=Formato_de_importação_desconhecido Web_search=Pesquisa_na_Web -Allow_file_links_relative_to_each_bib_file's_location=Permitir_links_de_arquivos_relativos_ao_local_do_arquivo_.bib Style_selection=Seleção_de_estilo No_valid_style_file_defined=Nenhum_estilo_válido_definido Choose_pattern=Escolher_modelo diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index e0fd33207628..b2966a16ef78 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1735,7 +1735,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=Не_удалось_открыть_%0 Unknown_import_format=Неизвестный_формат_импорта Web_search=Веб-поиск -Allow_file_links_relative_to_each_bib_file's_location=Разрешить_относительные_ссылки_для_расположения_каждого_файла_BibTeX Style_selection=Выбор_стиля No_valid_style_file_defined=Не_определен_допустимый_файл_стиля Choose_pattern=Выбор_шаблона diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index b351a03f2ae0..9c31f8f2254b 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -64,7 +64,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?= All_fields=Alla_fält All_key_bindings_will_be_reset_to_their_defaults.=Alla_tangentbordsbindingar_kommer_att_återställas_till_standardvärden. All_subgroups_(recursively)=Alla_undergrupper_(rekursivt) -Allow_file_links_relative_to_each_bib_file's_location= Allow_overwriting_existing_links.=Tillåt_att_befintliga_länkar_skrivs_över. Always_add_letter_(a,_b,_...)_to_generated_keys=Lägg_alltid_till_en_bokstav_(a,_b_...)_på_genererade_nycklar Always_reformat_.bib_file_on_save_and_export=Formattera_allid_om_.bib-filen_vid_när_den_sparas_eller_exporteras diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index ed98752ddde1..df52e768256e 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1012,7 +1012,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=%0_açılamıyor Unknown_import_format=Bilinmeyen_içe_aktarım_biçimi Web_search=Ağ_araması -Allow_file_links_relative_to_each_bib_file's_location=Her_bib_dosyasının_konumuna_göre_dosya_bağlantılarına_izin_ver Style_selection=Stil_seçimi No_valid_style_file_defined=Geçerli_stil_dosyası_tanımlanmadı diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index bf86774bc1b5..9574627595b4 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1765,7 +1765,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0= Unknown_import_format= Web_search= -Allow_file_links_relative_to_each_bib_file's_location= Style_selection= No_valid_style_file_defined= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 1f2cfeb6a282..0afe429bc47c 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1067,7 +1067,6 @@ If_possible,_normalize_this_list_of_names_to_conform_to_standard_BibTeX_name_for Could_not_open_%0=无法打开_%0 Unknown_import_format=未知的导入格式 Web_search=网页搜索 -Allow_file_links_relative_to_each_bib_file's_location=允许文件链接使用基于_.bib_文件位置的相对路径 Style_selection=引用样式选择 No_valid_style_file_defined=没有找到合法的_style_文件 From 8de514a866febc6d33a0fddbc90ec58aaebeff21 Mon Sep 17 00:00:00 2001 From: Christoph Hochreiner Date: Tue, 10 May 2016 10:28:47 +0200 Subject: [PATCH 038/268] Preliminary fix for #1340 (#1344) --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java | 2 +- src/main/resources/l10n/JabRef_da.properties | 1 + src/main/resources/l10n/JabRef_de.properties | 1 + src/main/resources/l10n/JabRef_en.properties | 1 + src/main/resources/l10n/JabRef_es.properties | 1 + src/main/resources/l10n/JabRef_fa.properties | 1 + src/main/resources/l10n/JabRef_fr.properties | 1 + src/main/resources/l10n/JabRef_in.properties | 1 + src/main/resources/l10n/JabRef_it.properties | 1 + src/main/resources/l10n/JabRef_ja.properties | 1 + src/main/resources/l10n/JabRef_nl.properties | 2 +- src/main/resources/l10n/JabRef_no.properties | 1 + src/main/resources/l10n/JabRef_pt_BR.properties | 1 + src/main/resources/l10n/JabRef_ru.properties | 1 + src/main/resources/l10n/JabRef_sv.properties | 1 + src/main/resources/l10n/JabRef_tr.properties | 1 + src/main/resources/l10n/JabRef_vi.properties | 1 + src/main/resources/l10n/JabRef_zh.properties | 1 + 19 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17b06fea0420..a3f662de3f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed: Move linked files to default directory works again - Fixed [#1327](https://github.com/JabRef/jabref/issues/1327): PDF cleanup changes order of linked pdfs - Fixed [#1313](https://github.com/JabRef/jabref/issues/1313): Remove UI for a configuration option which was no longer available +- Fixed [#1340](https://github.com/JabRef/jabref/issues/1340): Edit -> Mark Specific Color Dysfunctional on OSX ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java b/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java index 798dff369561..11ee6b3cb29f 100644 --- a/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java +++ b/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java @@ -50,7 +50,7 @@ public MarkEntriesAction(JabRefFrame frame, int level) { this.level = level; //menuItem = new JMenuItem(Globals.menuTitle("Mark entries").replace("&","")); - menuItem = new JMenuItem(" "); + menuItem = new JMenuItem(Localization.lang("Level") + " " + level + " "); menuItem.setMnemonic(String.valueOf(level + 1).charAt(0)); menuItem.setBackground(Globals.prefs.getColor(JabRefPreferences.MARKED_ENTRY_BACKGROUND + this.level)); menuItem.setOpaque(true); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index f0b1fccfb52f..0543d9396ba7 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -439,6 +439,7 @@ LaTeX_AUX_file=LaTeX_AUX-fil Leave_file_in_its_current_directory=Lad_filen_ligge_i_biblioteket,_den_ligger_i_nu Left=Venstre +Level= Limit_to_fields=Begræns_til_følgende_felter Limit_to_selected_entries=Begræns_til_valgte_poster diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 4c9477791700..af36ce8c9951 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -805,6 +805,7 @@ LaTeX_AUX_file=LaTeX_AUX-Datei Leave_file_in_its_current_directory=Datei_im_aktuellen_Verzeichnis_lassen Left=Links +Level=Ebene Limit_to_fields=Auf_folgende_Felder_begrenzen diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 8b7424728447..e26df8fc985b 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -768,6 +768,7 @@ LaTeX_AUX_file=LaTeX_AUX_file Leave_file_in_its_current_directory=Leave_file_in_its_current_directory Left=Left +Level=Level Limit_to_fields=Limit_to_fields diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index c7f885594c77..6b69b83c7bfa 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -410,6 +410,7 @@ Last_modified=Modificado_por_última_vez LaTeX_AUX_file=Archivo_LaTeX_AUX Leave_file_in_its_current_directory=Dejar_el_archivo_en_su_directorio_actual Left=Dejar +Level= Limit_to_fields=Limitar_a_los_campos Limit_to_selected_entries=Limitar_a_las_entradas_seleccionadas Link=Enlace diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 67d94b1286ef..826f96e5cdfb 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -777,6 +777,7 @@ LaTeX_AUX_file= Leave_file_in_its_current_directory= Left= +Level= Limit_to_fields= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index b560f0577201..aaf7ae84ec27 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -410,6 +410,7 @@ Last_modified=Dernier_modifié LaTeX_AUX_file=Fichier_LaTeX_AUX Leave_file_in_its_current_directory=Laisser_le_fichier_dans_son_répertoire_courant Left=Gauche +Level= Limit_to_fields=Restreindre_aux_champs Limit_to_selected_entries=Restreindre_aux_seules_entrées_sélectionnées Link=Lien diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index b6bc934a8c62..0ff4ece9e422 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -409,6 +409,7 @@ Last_modified=Terakhir_diubah LaTeX_AUX_file=berkas_LaTeX_AUX Leave_file_in_its_current_directory=Tinggalkan_berkas_di_direktori_yg_sekarang Left=Kiri +Level= Limit_to_fields=Batasi_ke_bidang Limit_to_selected_entries=Batasi_ke_entri_pilihan Link=Tautan diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 0dd7106f9bfe..e1596e73062c 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -444,6 +444,7 @@ LaTeX_AUX_file=File_AUX_LaTeX Leave_file_in_its_current_directory=Lascia_il_file_nella_cartella_corrente Left=Sinistra +Level= Limit_to_fields=Restrizioni_ai_campi Limit_to_selected_entries=Restrizioni_alle_voci_selezionate diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index afc8680aa3b1..17712231bef1 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -788,6 +788,7 @@ LaTeX_AUX_file=LaTeX_AUXファイル Leave_file_in_its_current_directory=ファイルを現在のディレクトリに置いておく。 Left=左 +Level= Limit_to_fields=以下のフィールドに制限 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 15aa93f20a80..bb7b381833a8 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -805,7 +805,7 @@ LaTeX_AUX_file=LaTeX_AUX-bestand Leave_file_in_its_current_directory= Left=Links - +Level= Limit_to_fields=De_volgende_velden_begrenzen diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 4770b8737b29..fb401a375e9b 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -859,6 +859,7 @@ Leave_file_in_its_current_directory=La_filen_ligge_i_katalogen_den_ligger_i_n\u0 Left=Venstre +Level= Limit_to_fields=Begrens_til_f\u00f8lgende_felter diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 9a173f8cf9d4..4250ae22f20f 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -410,6 +410,7 @@ Last_modified=Última_modificação LaTeX_AUX_file=Arquivo_LaTeX_AUX Leave_file_in_its_current_directory=Manter_arquivos_em_seu_diretório_atual Left=Esquerdo(a) +Level= Limit_to_fields=Limitar_aos_campos Limit_to_selected_entries=Limitar_às_referência_selecionadas Link=Linkar diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index b2966a16ef78..dbd1bfbc2d18 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -773,6 +773,7 @@ LaTeX_AUX_file=Файл_AUX_для_LaTeX Leave_file_in_its_current_directory=Сохранить_файл_в_текущем_каталоге Left=Левый +Level= Limit_to_fields=Ограничение_для_полей diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 9c31f8f2254b..9b548c03f314 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -644,6 +644,7 @@ Last_modified=Senast_ändrad Leave_file_in_its_current_directory=Lämna_filen_i_nuvarande_mapp Leave_this_dialog.=Lämna_denna_dialog. Left=Vänster +Level= Left_entry=Vänster_post Limit_to_fields=Begränsa_till_fält Limit_to_selected_entries=Begränsa_till_valda_poster diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index df52e768256e..39595632a530 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -410,6 +410,7 @@ Last_modified=Son_değiştirme LaTeX_AUX_file=LaTex_AUX_dosyası Leave_file_in_its_current_directory=Dosyayı_şimdiki_dizininde_bırak Left=Sol +Level= Limit_to_fields=Alanlara_kısıtla Limit_to_selected_entries=Seçili_girdilere_kısıtla Link=Link diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 9574627595b4..093556ebfda6 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -790,6 +790,7 @@ LaTeX_AUX_file=Tập_tin_LaTeX_AUX Leave_file_in_its_current_directory=Giữ_tập_tin_trong_thư_mục_hiện_tại_của_nó Left=Trái +Level= Limit_to_fields=Giới_hạn_theo_các_trường diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 0afe429bc47c..64bce8a94360 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -406,6 +406,7 @@ Language=语言 Last_modified=上次修改的 Leave_file_in_its_current_directory=保留文件的当前位置不改变。 Left=Left +Level= Limit_to_fields=限制范围到域 Limit_to_selected_entries=限制范围为选中的记录 Link=链接 From 8cb3b2508876a1ecfc3e98faa02a19167d2bac97 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Tue, 10 May 2016 10:42:20 +0200 Subject: [PATCH 039/268] Fix link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bcd10ed8da3..81856cd0ae8a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ We use [install4j], the multi-platform installer builder. ### Background -JabRef is a graphical Java application for editing [BibTeX] and [Biblatex] (`.bib`) databases. +JabRef is a graphical Java application for editing [BibTeX] and [Biblatex] `.bib` databases. JabRef lets you organize your entries into overlapping logical groups, and with a single click limit your view to a single group or an intersection or union of several groups. You can customize the entry information shown in the main window, and sort by any of the standard BibTeX fields. JabRef can autogenerate BibTeX keys for your entries. From 34fbe7681dec9d102392eccd0ed2e59139e69ad8 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 10 May 2016 11:00:19 +0200 Subject: [PATCH 040/268] =?UTF-8?q?Removed=20possibility=20to=20automatica?= =?UTF-8?q?lly=20add=20braces=20via=20Option=20-=20Preferen=E2=80=A6=20(#1?= =?UTF-8?q?368)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Removed possibility to automatically add braces via Option - Preferences - File - Store the following fields with braces around capital letters. Please use save actions instead for adding braces automatically. * Remove unused imports --- CHANGELOG.md | 2 +- .../java/net/sf/jabref/JabRefPreferences.java | 17 +---------------- .../sf/jabref/exporter/LatexFieldFormatter.java | 4 ---- .../net/sf/jabref/gui/preftabs/FileTab.java | 13 +------------ .../importer/fileformat/BibtexParser.java | 8 -------- src/main/resources/l10n/JabRef_da.properties | 1 - src/main/resources/l10n/JabRef_de.properties | 2 -- src/main/resources/l10n/JabRef_en.properties | 2 -- src/main/resources/l10n/JabRef_es.properties | 1 - src/main/resources/l10n/JabRef_fa.properties | 2 -- src/main/resources/l10n/JabRef_fr.properties | 3 +-- src/main/resources/l10n/JabRef_in.properties | 1 - src/main/resources/l10n/JabRef_it.properties | 1 - src/main/resources/l10n/JabRef_ja.properties | 2 -- src/main/resources/l10n/JabRef_nl.properties | 2 -- src/main/resources/l10n/JabRef_no.properties | 2 -- src/main/resources/l10n/JabRef_pt_BR.properties | 1 - src/main/resources/l10n/JabRef_ru.properties | 2 -- src/main/resources/l10n/JabRef_sv.properties | 3 +-- src/main/resources/l10n/JabRef_tr.properties | 1 - src/main/resources/l10n/JabRef_vi.properties | 2 -- src/main/resources/l10n/JabRef_zh.properties | 1 - 22 files changed, 5 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3f662de3f12..69afb7d9a6e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic - Removed support of old groups format, which was used prior to JabRef version 1.6. If you happen to have a 10 years old .bib file, then JabRef 3.3 can be used to convert it to the current format. - +- Removed possibility to automatically add braces via Option - Preferences - File - Store the following fields with braces around capital letters. Please use save actions instead for adding braces automatically. diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index e523f4e0d576..bbe90f360ac6 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -256,7 +256,6 @@ public class JabRefPreferences { public static final String MARK_IMPORTED_ENTRIES = "markImportedEntries"; public static final String GENERATE_KEYS_AFTER_INSPECTION = "generateKeysAfterInspection"; public static final String NON_WRAPPABLE_FIELDS = "nonWrappableFields"; - public static final String PUT_BRACES_AROUND_CAPITALS = "putBracesAroundCapitals"; public static final String RESOLVE_STRINGS_ALL_FIELDS = "resolveStringsAllFields"; public static final String DO_NOT_RESOLVE_STRINGS_FOR = "doNotResolveStringsFor"; public static final String PREVIEW_PRINT_BUTTON = "previewPrintButton"; @@ -407,7 +406,6 @@ public class JabRefPreferences { private final Preferences prefs; - private final Set putBracesAroundCapitalsFields = new HashSet<>(4); private final Set nonWrappableFields = new HashSet<>(5); private GlobalLabelPattern keyPattern; @@ -765,7 +763,6 @@ private JabRefPreferences() { defaults.put(PREVIEW_PRINT_BUTTON, Boolean.FALSE); defaults.put(DO_NOT_RESOLVE_STRINGS_FOR, "url"); defaults.put(RESOLVE_STRINGS_ALL_FIELDS, Boolean.FALSE); - defaults.put(PUT_BRACES_AROUND_CAPITALS, "");//"title;journal;booktitle;review;abstract"); defaults.put(NON_WRAPPABLE_FIELDS, "pdf;ps;url;doi;file"); defaults.put(GENERATE_KEYS_AFTER_INSPECTION, Boolean.TRUE); defaults.put(MARK_IMPORTED_ENTRIES, Boolean.TRUE); @@ -905,21 +902,9 @@ public void setLanguageDependentDefaultValues() { defaults.put(EMAIL_SUBJECT, Localization.lang("References")); } - public boolean putBracesAroundCapitals(String fieldName) { - return putBracesAroundCapitalsFields.contains(fieldName); - } - public void updateSpecialFieldHandling() { - putBracesAroundCapitalsFields.clear(); - String fieldString = get(PUT_BRACES_AROUND_CAPITALS); - if (!fieldString.isEmpty()) { - String[] fields = fieldString.split(";"); - for (String field : fields) { - putBracesAroundCapitalsFields.add(field.trim()); - } - } nonWrappableFields.clear(); - fieldString = get(NON_WRAPPABLE_FIELDS); + String fieldString = get(NON_WRAPPABLE_FIELDS); if (!fieldString.isEmpty()) { String[] fields = fieldString.split(";"); for (String field : fields) { diff --git a/src/main/java/net/sf/jabref/exporter/LatexFieldFormatter.java b/src/main/java/net/sf/jabref/exporter/LatexFieldFormatter.java index 47159ff51b4e..be556ab1e343 100644 --- a/src/main/java/net/sf/jabref/exporter/LatexFieldFormatter.java +++ b/src/main/java/net/sf/jabref/exporter/LatexFieldFormatter.java @@ -86,10 +86,6 @@ public String format(String content, String fieldName) } String result = content; - boolean shouldWrapWithBraces = Globals.prefs.putBracesAroundCapitals(fieldName) && !BIBTEX_STRING.equals(fieldName); - if (shouldWrapWithBraces) { - result = StringUtil.putBracesAroundCapitals(result); - } // normalize newlines boolean shouldNormalizeNewlines = !result.contains(Globals.NEWLINE) && result.contains("\n"); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index 3c4aa2f30ee2..b4741a96e776 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -60,7 +60,6 @@ class FileTab extends JPanel implements PrefsTab { private final JCheckBox reformatFileOnSaveAndExport; private final JRadioButton resolveStringsStandard; private final JRadioButton resolveStringsAll; - private final JTextField bracesAroundCapitalsFields; private final JTextField nonWrappableFields; private final JTextField doNotResolveStringsFor; private final JSpinner autoSaveInterval; @@ -114,7 +113,6 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { reformatFileOnSaveAndExport = new JCheckBox(Localization.lang("Always reformat .bib file on save and export")); - bracesAroundCapitalsFields = new JTextField(25); nonWrappableFields = new JTextField(25); doNotResolveStringsFor = new JTextField(30); @@ -133,11 +131,7 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { builder.append(backup, 3); builder.nextLine(); - JLabel label = new JLabel(Localization.lang("Store the following fields with braces around capital letters") + ":"); - builder.append(label); - builder.append(bracesAroundCapitalsFields); - builder.nextLine(); - label = new JLabel(Localization.lang("Do not wrap the following fields when saving") + ":"); + JLabel label = new JLabel(Localization.lang("Do not wrap the following fields when saving") + ":"); builder.append(label); builder.append(nonWrappableFields); builder.nextLine(); @@ -235,7 +229,6 @@ public void setValues() { resolveStringsAll.setSelected(prefs.getBoolean(JabRefPreferences.RESOLVE_STRINGS_ALL_FIELDS)); resolveStringsStandard.setSelected(!resolveStringsAll.isSelected()); doNotResolveStringsFor.setText(prefs.get(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR)); - bracesAroundCapitalsFields.setText(prefs.get(JabRefPreferences.PUT_BRACES_AROUND_CAPITALS)); nonWrappableFields.setText(prefs.get(JabRefPreferences.NON_WRAPPABLE_FIELDS)); autoSave.setSelected(prefs.getBoolean(JabRefPreferences.AUTO_SAVE)); @@ -285,10 +278,6 @@ public void storeSettings() { doNotResolveStringsFor.setText(prefs.get(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR)); boolean updateSpecialFields = false; - if (!bracesAroundCapitalsFields.getText().trim().equals(prefs.get(JabRefPreferences.PUT_BRACES_AROUND_CAPITALS))) { - prefs.put(JabRefPreferences.PUT_BRACES_AROUND_CAPITALS, bracesAroundCapitalsFields.getText()); - updateSpecialFields = true; - } if (!nonWrappableFields.getText().trim().equals(prefs.get(JabRefPreferences.NON_WRAPPABLE_FIELDS))) { prefs.put(JabRefPreferences.NON_WRAPPABLE_FIELDS, nonWrappableFields.getText()); updateSpecialFields = true; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 42c9d4ecd14a..ac323043d52d 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -28,14 +28,12 @@ import java.util.Map; import java.util.Objects; -import net.sf.jabref.Globals; import net.sf.jabref.MetaData; import net.sf.jabref.bibtex.FieldProperties; import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibEntry; @@ -553,12 +551,6 @@ private void parseField(BibEntry entry) throws IOException { skipWhitespace(); consume('='); String content = parseFieldContent(key); - // Now, if the field in question is set up to be fitted automatically - // with braces around - // capitals, we should remove those now when reading the field: - if (Globals.prefs.putBracesAroundCapitals(key)) { - content = StringUtil.removeBracesAroundCapitals(content); - } if (!content.isEmpty()) { if (entry.hasField(key)) { // The following hack enables the parser to deal with multiple diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 0543d9396ba7..dfe7e0485944 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -725,7 +725,6 @@ Statically_group_entries_by_manual_assignment=Grupper_poster_statisk_ved_manuel_ Status=Status Stop=Stop Store_journal_abbreviations=Gem_tidsskriftsforkortelser -Store_the_following_fields_with_braces_around_capital_letters=Gem_de_følgende_felter_med_krøllede_parenteser_om_store_bogstaver Stored_entry=Post_gemt Strings=Strenge Strings_for_database=Strenge_for_database diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index af36ce8c9951..60f2d32dc14d 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1345,8 +1345,6 @@ Stop=Stop Store_journal_abbreviations=Abkürzungen_der_Zeitschriften_speichern -Store_the_following_fields_with_braces_around_capital_letters=Die_folgenden_Felder_mit_geschweiften_Klammern_um_die_Großbuchstaben_speichern - Stored_entry=Eintrag_gespeichert Strings=Ersetzen diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index e26df8fc985b..5923968447c1 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1267,8 +1267,6 @@ Stop=Stop Store_journal_abbreviations=Store_journal_abbreviations -Store_the_following_fields_with_braces_around_capital_letters=Store_the_following_fields_with_braces_around_capital_letters - Stored_entry=Stored_entry Strings=Strings diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 6b69b83c7bfa..e654118807a4 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -677,7 +677,6 @@ Statically_group_entries_by_manual_assignment=Agrupar_entradas_estadísticamente Status=Estado Stop=Parar Store_journal_abbreviations=Almacenar_abreviaturas_de_revista -Store_the_following_fields_with_braces_around_capital_letters=Guardar_los_campos_a_continuación_con_llaves_alrededor_de_las_mayúsculas Stored_entry=Entrada_almacenada Strings=Cadenas Strings_for_database=Cadenas_para_base_de_datos diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 826f96e5cdfb..56784f5985c5 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1306,8 +1306,6 @@ Stop= Store_journal_abbreviations= -Store_the_following_fields_with_braces_around_capital_letters= - Stored_entry= Strings= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index aaf7ae84ec27..0d104ccdf89c 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -677,7 +677,6 @@ Statically_group_entries_by_manual_assignment=Grouper_manuellement_les_entrées Status=Etat Stop=Arrêt Store_journal_abbreviations=Stocker_les_abréviations_de_journaux -Store_the_following_fields_with_braces_around_capital_letters=Stocker_les_champs_suivants_avec_des_accolades_autour_des_lettres_capitales Stored_entry=Entrée_enregistrée Strings=Chaîne Strings_for_database=Chaînes_pour_la_base @@ -1230,7 +1229,7 @@ Save_entries_ordered_as_specified=Enregistrer_les_entrées_dans_l'ordre_spécifi Save_sort_order=Enregistrer_l'ordre_de_tri Show_extra_columns=Montrer_les_colonnes_supplémentaires Parsing_error=Erreur_de_traitement -illegal_backslash_expression=Expression_avec_barre_oblique_inversée_(\)_illégale +illegal_backslash_expression=Expression_avec_barre_oblique_inversée_(\\)_illégale Move_to_group=Déplacer_vers_le_groupe diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 0ff4ece9e422..2b8614310b73 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -676,7 +676,6 @@ Statically_group_entries_by_manual_assignment=Entri_grup_statik_secara_penerapan Status=Status Stop=Berhenti Store_journal_abbreviations=Simpan_singkatan_jurnal -Store_the_following_fields_with_braces_around_capital_letters=Simpan_bidang_berikut_dengan_kurawal_melingkupi_huruf_besar Stored_entry=Entri_yang_disimpan Strings=String Strings_for_database=String_untuk_basisdata diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index e1596e73062c..4e11ece43094 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -738,7 +738,6 @@ Statically_group_entries_by_manual_assignment=Raggruppa_manualmente_le_voci Status=Stato Stop=Arresta Store_journal_abbreviations=Registra_le_abbreviazioni_delle_riviste -Store_the_following_fields_with_braces_around_capital_letters=Registra_i_seguenti_campi_con_lettere_maiuscole_tra_parentesi_graffe_addizionali Stored_entry=Voce_registrata Strings=Stringa Strings_for_database=Stringhe_per_il_database diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 17712231bef1..9b4192b26085 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1324,8 +1324,6 @@ Stop=停止 Store_journal_abbreviations=学術誌名の短縮形を保管 -Store_the_following_fields_with_braces_around_capital_letters=以下のフィールドは、大文字の周囲を中括弧で囲って保存 - Stored_entry=項目を保管 Strings=文字列 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index bb7b381833a8..bcc741d028dd 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1342,8 +1342,6 @@ Stop=Stop Store_journal_abbreviations=Tijdschrift_afkortingen_opslaan -Store_the_following_fields_with_braces_around_capital_letters=Volgende_velden_met_haakjes_rond_hoofdletters_opslaan - Stored_entry=Entry_opgeslagen Strings=Constanten diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index fb401a375e9b..c15d23b4706e 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1443,8 +1443,6 @@ Stop=Stopp Store_journal_abbreviations=Lagre_journalforkortelser -Store_the_following_fields_with_braces_around_capital_letters=Lagre_de_f\u00f8lgende_feltene_med_kr\u00f8llparenteser_rundt_store_bokstaver - Stored_entry=Lagret_enhet Strings=Strenger diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 4250ae22f20f..7617399c31d6 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -677,7 +677,6 @@ Statically_group_entries_by_manual_assignment=Agrupar_referências_manualmente Status=Status Stop=Parar Store_journal_abbreviations=Armazenar_abreviações_de_periódicos -Store_the_following_fields_with_braces_around_capital_letters=Armazena_os_seguintes_campos_com_chaves_circudando_letras_maísculas Stored_entry=Referência_armazenada Strings=Strings Strings_for_database=Strings_para_a_base_de_dados diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index dbd1bfbc2d18..ecf8df26577b 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1298,8 +1298,6 @@ Stop=Остановить Store_journal_abbreviations=Сохранить_сокращения_для_журналов -Store_the_following_fields_with_braces_around_capital_letters=Сохранить_следующие_поля_с_заглавными_буквами_в_скобках - Stored_entry=Запись_сохранена Strings=Строки diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 9b548c03f314..c3317f60ab76 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1011,7 +1011,7 @@ Scan_directory=Sök_igenom_mapp Search=Sök Search_%0=Sök_%0 Search_expression=Sökuttryck -Search_failed\:_illegal_search_expression=Sökning_misslyckades:\_ogiltigt_sökuttryck +Search_failed\:_illegal_search_expression=Sökning_misslyckades\:_ogiltigt_sökuttryck Search_for=Sök_efter Search_globally=Sök_globalt Search_in_all_open_databases=Sök_i_alla_öppna_databaser @@ -1124,7 +1124,6 @@ Statically_group_entries_by_manual_assignment= Status=Status Stop=Stanna Store_journal_abbreviations=Spara_tidskriftsförkortningar -Store_the_following_fields_with_braces_around_capital_letters= Stored_entry=Sparade_post String_dialog,_add_string=Strängdialog,_lägg_till_sträng String_dialog,_remove_string=Strängdialog,_ta_bort_sträng diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 39595632a530..2631da78b1a4 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -677,7 +677,6 @@ Statically_group_entries_by_manual_assignment=Elle_atanmış_durağan_grup_girdi Status=Durum Stop=Dur Store_journal_abbreviations=Dergi_kısaltmalarını_depola -Store_the_following_fields_with_braces_around_capital_letters=Aşağıdaki_alanları_büyük_harflerin_etrafında_küme_parantezleriyle_depola Stored_entry=Depolanmış_girdi Strings=Dizgeler Strings_for_database=Veritabanı_için_dizgeler diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 093556ebfda6..9302f12524a0 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1326,8 +1326,6 @@ Stop=Dừng Store_journal_abbreviations=Lưu_trữ_viết_tắt_các_tạp_chí -Store_the_following_fields_with_braces_around_capital_letters=Lưu_trữ_các_trường_sau_với_ngoặc_móc_quanh_các_chữ_hoa - Stored_entry=Mục_được_lưu_trữ Strings=Các_chuỗi diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 64bce8a94360..bd0cc1e382e3 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -691,7 +691,6 @@ Statically_group_entries_by_manual_assignment=手动创建静态分组 Status=状态 Stop=停止 Store_journal_abbreviations=储存期刊缩写 -Store_the_following_fields_with_braces_around_capital_letters=储存下列域时使用大括号包裹大写字母 Stored_entry=储存的记录 String_dialog,_add_string=简写字串对话框,添加简写字串 String_dialog,_remove_string=简写字串对话框,删除简写字串 From 0b55a7f5e74b39ab22b84ae1c71539f9e1d2e77f Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Tue, 10 May 2016 11:07:14 +0200 Subject: [PATCH 041/268] Win install (#1367) * Resolves #1364 Windows: install to APPDATA directory for non-admin users --- CHANGELOG.md | 2 ++ jabref.install4j | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69afb7d9a6e1..1a75c8cc3d67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed [#1327](https://github.com/JabRef/jabref/issues/1327): PDF cleanup changes order of linked pdfs - Fixed [#1313](https://github.com/JabRef/jabref/issues/1313): Remove UI for a configuration option which was no longer available - Fixed [#1340](https://github.com/JabRef/jabref/issues/1340): Edit -> Mark Specific Color Dysfunctional on OSX +- Fixed [#1245](https://github.com/JabRef/jabref/issues/1245): Empty jstyle properties can now be specified as "" +- Fixed [#1364](https://github.com/JabRef/jabref/issues/1364): Windows: install to LOCALAPPDATA directory for non-admin users ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/jabref.install4j b/jabref.install4j index a1cdc409739b..dd572173f3b0 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -168,7 +168,11 @@ if (Util.hasFullAdminRights()) { context.setInstallationDirectory(context.getInstallationDirectory()); } else { - context.setInstallationDirectory(new File(System.getProperty("user.home"), "JabRef")); + if (Util.isAtLeastWindowsVista()) { + context.setInstallationDirectory(new File(System.getProperty("LOCALAPPDATA"), "JabRef")); + } else { + context.setInstallationDirectory(new File(System.getProperty("user.home"), "JabRef")); + } } return true; From b512d96305f57db324090b153456055ffb4d9aea Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 10 May 2016 14:11:31 +0200 Subject: [PATCH 042/268] =?UTF-8?q?Add=20integrity=20check=20detecting=20b?= =?UTF-8?q?ooktitles=20ending=20with=20"conference=20on"=20=E2=80=A6=20(#1?= =?UTF-8?q?287)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add integrity check detecting booktitles ending with "conference on" which is a typical error upon downloading .bib entries from the web * Script to remove any annoying git markers * Fix issue with dash instead of underscore in l10n key --- ...emove-git-markers-in-localization-files.rb | 4 ++++ .../logic/integrity/IntegrityCheck.java | 20 +++++++++++++++++++ src/main/resources/l10n/JabRef_da.properties | 1 + src/main/resources/l10n/JabRef_de.properties | 1 + src/main/resources/l10n/JabRef_en.properties | 1 + src/main/resources/l10n/JabRef_es.properties | 1 + src/main/resources/l10n/JabRef_fa.properties | 1 + src/main/resources/l10n/JabRef_fr.properties | 1 + src/main/resources/l10n/JabRef_in.properties | 1 + src/main/resources/l10n/JabRef_it.properties | 1 + src/main/resources/l10n/JabRef_ja.properties | 2 ++ src/main/resources/l10n/JabRef_nl.properties | 1 + src/main/resources/l10n/JabRef_no.properties | 1 + .../resources/l10n/JabRef_pt_BR.properties | 1 + src/main/resources/l10n/JabRef_ru.properties | 1 + src/main/resources/l10n/JabRef_sv.properties | 1 + src/main/resources/l10n/JabRef_tr.properties | 1 + src/main/resources/l10n/JabRef_vi.properties | 1 + src/main/resources/l10n/JabRef_zh.properties | 1 + .../logic/integrity/IntegrityCheckTest.java | 6 ++++++ 20 files changed, 48 insertions(+) create mode 100644 scripts/remove-git-markers-in-localization-files.rb diff --git a/scripts/remove-git-markers-in-localization-files.rb b/scripts/remove-git-markers-in-localization-files.rb new file mode 100644 index 000000000000..0f4a5cb1a37f --- /dev/null +++ b/scripts/remove-git-markers-in-localization-files.rb @@ -0,0 +1,4 @@ +# call from project root via $ ruby remove-git-markers-in-localization-files.rb +Dir.glob("src/main/resources/l10n/*.properties") do |f| + File.write(f, IO.readlines(f).map { |line| line.strip.start_with?("<<<<<<<") || line.strip.start_with?("=======") || line.strip.start_with?(">>>>>>>") ? "" : line }.join("")) +end diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 060729ec9601..0b6555f93ee0 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -63,6 +64,7 @@ private List checkBibtexEntry(BibEntry entry) { result.addAll(new AbbreviationChecker("booktitle").check(entry)); result.addAll(new BibStringChecker().check(entry)); result.addAll(new HTMLCharacterChecker().check(entry)); + result.addAll(new BooktitleChecker().check(entry)); result.addAll(new ISSNChecker().check(entry)); return result; @@ -91,6 +93,24 @@ public List check(BibEntry entry) { } } + private static class BooktitleChecker implements Checker { + + @Override + public List check(BibEntry entry) { + String field = "booktitle"; + Optional value = entry.getFieldOptional(field); + if (!value.isPresent()) { + return Collections.emptyList(); + } + + if (value.get().toLowerCase(Locale.ENGLISH).endsWith("conference on")) { + return Collections.singletonList(new IntegrityMessage(Localization.lang("booktitle ends with 'conference on'"), entry, field)); + } + + return Collections.emptyList(); + } + } + private static class AbbreviationChecker implements Checker { private final String field; diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index dfe7e0485944..08e2de12d7a6 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1670,6 +1670,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 60f2d32dc14d..83df8b08113c 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2387,6 +2387,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 5923968447c1..b278b25ee8d0 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2249,6 +2249,7 @@ word=word Show_symmetric_diff=Show_symmetric_diff HTML_encoded_character_found=HTML_encoded_character_found +booktitle_ends_with_'conference_on'=booktitle_ends_with_'conference_on' All_external_files=All_external_files diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index e654118807a4..43caaff7a1e2 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1571,6 +1571,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 56784f5985c5..c457e0374bd8 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2357,6 +2357,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 0d104ccdf89c..37fee6e845a3 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1626,3 +1626,4 @@ Syntax_error_in_regular-expression_pattern= Copy_version_to_clipboard= Copied_version_to_clipboard= +booktitle_ends_with_'conference_on'= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 2b8614310b73..8cef82c38369 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1590,6 +1590,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 4e11ece43094..4832dde4c766 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1690,6 +1690,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 9b4192b26085..0c1d7fe82b8b 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2346,3 +2346,5 @@ Syntax_error_in_regular-expression_pattern=正規表現パターン中の文法 Copy_version_to_clipboard=バージョンをクリップボードにコピー Copied_version_to_clipboard=クリップボードにコピーされたバージョン + +booktitle_ends_with_'conference_on'= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index bcc741d028dd..3ea0d7396ecc 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2366,6 +2366,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index c15d23b4706e..0c17aad69cb1 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2762,6 +2762,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 7617399c31d6..308c08517ba2 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1584,6 +1584,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index ecf8df26577b..b8d018410d02 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2334,6 +2334,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index c3317f60ab76..ce7e8400fbf0 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1526,6 +1526,7 @@ word=ord Show_symmetric_diff=Visa_skillnad_symmetriskt +booktitle_ends_with_'conference_on'= HTML_encoded_character_found=HTML-kodade_tecken_hittades All_external_files= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 2631da78b1a4..f5aca2bfad47 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1556,6 +1556,7 @@ Move_linked_files_to_default_file_directory_%0=Bağlantılı_dosyaları_öntanı Lookup_DOI=DOI_bul No_DOI_found=_DOI_bulunamadi +booktitle_ends_with_'conference_on'= Audio_CD=Müzik_CDsi British_patent=İngiliz_patenti British_patent_request=İngiliz_patent_başvurusu diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 9302f12524a0..ed35cb2442cb 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2358,6 +2358,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index bd0cc1e382e3..dd2ea3a2b78c 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1597,6 +1597,7 @@ Show_symmetric_diff= HTML_encoded_character_found= +booktitle_ends_with_'conference_on'= All_external_files= OpenOffice/LibreOffice_integration= diff --git a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java index 600d69d467a1..4e60f04d3a96 100644 --- a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java @@ -138,6 +138,12 @@ public void testTypeChecks() { assertWrong(createContext("pages", "11--15", "proceedings")); } + @Test + public void testBooktitleChecks() { + assertCorrect(createContext("booktitle", "2014 Fourth International Conference on Digital Information and Communication Technology and it's Applications (DICTAP)", "proceedings")); + assertWrong(createContext("booktitle", "Digital Information and Communication Technology and it's Applications (DICTAP), 2014 Fourth International Conference on", "proceedings")); + } + @Test public void testPageNumbersChecks() { assertCorrect(createContext("pages", "1--2")); From 2e13dca4f23b3559fe8790f8f26234e8aa40a6f1 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 10 May 2016 16:00:55 +0200 Subject: [PATCH 043/268] Better integrity check: allow single dash for biblatex users in the pages field --- .../logic/integrity/IntegrityCheck.java | 41 ++++++++++++++++++- .../logic/integrity/IntegrityCheckTest.java | 19 ++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 0b6555f93ee0..0a93ac463600 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -52,11 +52,13 @@ private List checkBibtexEntry(BibEntry entry) { if (!bibDatabaseContext.isBiblatexMode()) { result.addAll(new TitleChecker().check(entry)); + result.addAll(new PagesChecker().check(entry)); + } else { + result.addAll(new BiblatexPagesChecker().check(entry)); } result.addAll(new BracketChecker("title").check(entry)); result.addAll(new YearChecker().check(entry)); - result.addAll(new PagesChecker().check(entry)); result.addAll(new UrlChecker().check(entry)); result.addAll(new FileChecker(bibDatabaseContext).check(entry)); result.addAll(new TypeChecker().check(entry)); @@ -349,6 +351,43 @@ public List check(BibEntry entry) { } } + /** + * Same as {@link PagesChecker} but allows single dash as well + */ + private static class BiblatexPagesChecker implements Checker { + + private static final String PAGES_EXP = "" + + "\\A" // begin String + + "\\d+" // number + + "(?:" // non-capture group + + "\\+|\\-{1,2}\\d+" // + or --number (range) + + ")?" // optional group + + "(?:" // non-capture group + + "," // comma + + "\\d+(?:\\+|\\-{1,2}\\d+)?" // repeat former pattern + + ")*" // repeat group 0,* + + "\\z"; // end String + + private static final Predicate VALID_PAGE_NUMBER = Pattern.compile(PAGES_EXP).asPredicate(); + + /** + * Checks, if the page numbers String conforms to the BibTex manual + */ + @Override + public List check(BibEntry entry) { + Optional value = entry.getFieldOptional("pages"); + if (!value.isPresent()) { + return Collections.emptyList(); + } + + if (!VALID_PAGE_NUMBER.test(value.get().trim())) { + return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a valid page number range"), entry, "pages")); + } + + return Collections.emptyList(); + } + } + private static class BibStringChecker implements Checker { // Detect # if it doesn't have a \ in front of it or if it starts the string diff --git a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java index 4e60f04d3a96..5fe5142939ef 100644 --- a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java @@ -159,6 +159,21 @@ public void testPageNumbersChecks() { assertCorrect(createContext("pages", "7+,41--43,73")); } + @Test + public void testBiblatexPageNumbersChecks() { + assertCorrect(withMode(createContext("pages", "1--2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext("pages", "12"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext("pages", "1-2"), BibDatabaseMode.BIBLATEX)); // only diff to bibtex + assertCorrect(withMode(createContext("pages", "1,2,3"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext("pages", "43+"), BibDatabaseMode.BIBLATEX)); + assertWrong(withMode(createContext("pages", "1 2"), BibDatabaseMode.BIBLATEX)); + assertWrong(withMode(createContext("pages", "{1}-{2}"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext("pages", "7,41,73--97"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext("pages", "7,41--42,73"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext("pages", "7--11,41--43,73"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext("pages", "7+,41--43,73"), BibDatabaseMode.BIBLATEX)); + } + @Test public void testBibStringChecks() { assertCorrect(createContext("title", "Not a single hash mark")); @@ -197,7 +212,7 @@ private BibDatabaseContext createContext(String field, String value, String type return new BibDatabaseContext(bibDatabase, new Defaults()); } - public BibDatabaseContext createContext(String field, String value, MetaData metaData) { + private BibDatabaseContext createContext(String field, String value, MetaData metaData) { BibEntry entry = new BibEntry(); entry.setField(field, value); BibDatabase bibDatabase = new BibDatabase(); @@ -205,7 +220,7 @@ public BibDatabaseContext createContext(String field, String value, MetaData met return new BibDatabaseContext(bibDatabase, metaData, new Defaults()); } - public BibDatabaseContext createContext(String field, String value) { + private BibDatabaseContext createContext(String field, String value) { return createContext(field, value, new MetaData()); } From 50fe6d7499239fa2f04354697411495b79691e74 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 10 May 2016 16:45:15 +0200 Subject: [PATCH 044/268] Fix #1365: Default label pattern back to "[auth][year]" --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/JabRefPreferences.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d139f5fe510..5b2319d50f69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed [#1340](https://github.com/JabRef/jabref/issues/1340): Edit -> Mark Specific Color Dysfunctional on OSX - Fixed [#1245](https://github.com/JabRef/jabref/issues/1245): Empty jstyle properties can now be specified as "" - Fixed [#1364](https://github.com/JabRef/jabref/issues/1364): Windows: install to LOCALAPPDATA directory for non-admin users +- Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to "[auth][year]" ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index bbe90f360ac6..bbbd74c289d0 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -717,7 +717,7 @@ private JabRefPreferences() { defaults.put(CONFIRM_DELETE, Boolean.TRUE); defaults.put(GRAY_OUT_NON_HITS, Boolean.TRUE); defaults.put(SEARCH_MODE_FLOAT, Boolean.FALSE); - defaults.put(DEFAULT_LABEL_PATTERN, "[authors3][year]"); + defaults.put(DEFAULT_LABEL_PATTERN, "[auth][year]"); defaults.put(PREVIEW_ENABLED, Boolean.TRUE); defaults.put(ACTIVE_PREVIEW, 0); defaults.put(PREVIEW_0, From e35766d98092999089fd32b9a28c69915f89bba9 Mon Sep 17 00:00:00 2001 From: Christian Bartsch Date: Tue, 3 May 2016 19:11:32 +0200 Subject: [PATCH 045/268] fix-796 --- CHANGELOG.md | 1 + .../java/net/sf/jabref/gui/UndoTest.java | 72 +++++++++++++++++++ .../SpecialFieldDatabaseChangeListener.java | 25 +++++-- 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 src/integrationTest/java/net/sf/jabref/gui/UndoTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b2319d50f69..d8f6c03413d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed [#1245](https://github.com/JabRef/jabref/issues/1245): Empty jstyle properties can now be specified as "" - Fixed [#1364](https://github.com/JabRef/jabref/issues/1364): Windows: install to LOCALAPPDATA directory for non-admin users - Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to "[auth][year]" +- Fixed [#796](https://github.com/JabRef/jabref/issues/796): Undoing more than one entry at the same time is now working ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java b/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java new file mode 100644 index 000000000000..907870cc6eb5 --- /dev/null +++ b/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java @@ -0,0 +1,72 @@ +package net.sf.jabref.gui; + +import java.io.File; + +import net.sf.jabref.JabRefMain; + +import org.assertj.swing.finder.JFileChooserFinder; +import org.assertj.swing.fixture.FrameFixture; +import org.assertj.swing.fixture.JFileChooserFixture; +import org.assertj.swing.fixture.JTableFixture; +import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase; +import org.junit.Test; + +import static org.assertj.swing.finder.WindowFinder.findFrame; +import static org.assertj.swing.launcher.ApplicationLauncher.application; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class UndoTest extends AssertJSwingJUnitTestCase { + + private AWTExceptionHandler awtExceptionHandler; + + @Override + protected void onSetUp() { + awtExceptionHandler = new AWTExceptionHandler(); + awtExceptionHandler.installExceptionDetectionInEDT(); + application(JabRefMain.class).start(); + + robot().waitForIdle(); + + robot().settings().timeoutToFindSubMenu(1_000); + robot().settings().delayBetweenEvents(50); + } + + private void exitJabRef(FrameFixture mainFrame) { + mainFrame.menuItemWithPath("File", "Quit").click(); + awtExceptionHandler.assertNoExceptions(); + } + + private String getTestFilePath(String fileName) { + return new File(this.getClass().getClassLoader().getResource(fileName).getFile()).getAbsolutePath(); + } + + private void importBibIntoNewDatabase(FrameFixture mainFrame, String path) { + mainFrame.menuItemWithPath("File", "Import into new database").click(); + + JFileChooserFixture openFileDialog = JFileChooserFinder.findFileChooser().withTimeout(10_000).using(robot()); + robot().settings().delayBetweenEvents(1); + openFileDialog.fileNameTextBox().enterText(path); + robot().settings().delayBetweenEvents(50); + openFileDialog.approve(); + } + + @Test + public void undoCutOfMultipleEntries() { + FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); + importBibIntoNewDatabase(mainFrame, getTestFilePath("testbib/testjabref.bib")); + + JTableFixture entryTable = mainFrame.table(); + assertTrue("The database must have at least 2 entries for the test to begin!", entryTable.rowCount() >= 2); + entryTable.selectRows(0, 1); + + int rowCount = entryTable.rowCount(); + mainFrame.menuItemWithPath("Edit", "Cut").click(); + mainFrame.menuItemWithPath("Edit", "Undo").click(); + assertEquals(rowCount, entryTable.rowCount()); + + mainFrame.menuItemWithPath("File", "Close database").click(); + exitJabRef(mainFrame); + } + +} diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java index ee823acd4024..070af993b29f 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java @@ -1,6 +1,20 @@ +/* Copyright (C) 2003-2016 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.specialfields; -import net.sf.jabref.JabRefGUI; import net.sf.jabref.event.EntryAddedEvent; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.logic.l10n.Localization; @@ -21,14 +35,15 @@ public static SpecialFieldDatabaseChangeListener getInstance() { } @Subscribe - public void listen(EntryAddedEvent EntryAddedEvent) { + public void listen(EntryAddedEvent event) { if (SpecialFieldsUtils.keywordSyncEnabled()) { - final BibEntry entry = EntryAddedEvent.getBibEntry(); + final BibEntry entry = event.getBibEntry(); // NamedCompount code similar to SpecialFieldUpdateListener NamedCompound nc = new NamedCompound(Localization.lang("Synchronized special fields based on keywords")); SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, nc); - nc.end(); - JabRefGUI.getMainFrame().getCurrentBasePanel().undoManager.addEdit(nc); + // Don't insert the compound into the undoManager, + // it would be added before the component which undoes the insertion of the entry and creates heavy problems + // (which prohibits the undo the deleting multiple entries) } } From ee344724c914e11aa34180f54206d7b34cd79bf5 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 10 May 2016 23:23:00 +0200 Subject: [PATCH 046/268] Register listener for correct entry --- src/main/java/net/sf/jabref/gui/PreviewPanel.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index ab6dfa58859d..bfba1e91cef8 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -278,9 +278,9 @@ public void setEntry(BibEntry newEntry) { if (entry.isPresent() && (entry.get() != newEntry)) { entry.ifPresent(e -> e.unregisterListener(this)); } - - entry.ifPresent(e -> e.registerListener(this)); - + if(newEntry != null) { + newEntry.registerListener(this); + } entry = Optional.ofNullable(newEntry); updateLayout(); From cd7a9921a076ec4a8273b49a9f81abd2434fdbfa Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 11 May 2016 08:28:39 +0200 Subject: [PATCH 047/268] Add registry entries for installation path (#1370) --- CHANGELOG.md | 1 + jabref.install4j | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8f6c03413d2..a2b91e0f3dde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Add LaTeX to Unicode converter as cleanup operation - Added an option in the about dialog to easily copy the version information of JabRef - Integrity check table can be sorted by clicking on column headings +- Added \SOFTWARE\Jabref 'Path' registry entry for installation path inside the installer ### Fixed - Fixed [#473](https://github.com/JabRef/jabref/issues/473): Values in an entry containing symbols like ' are now properly escaped for exporting to the database diff --git a/jabref.install4j b/jabref.install4j index dd572173f3b0..72037811a59c 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -371,6 +371,63 @@ return true; context.getBooleanVariable("addToDockAction") + + + + + + + + + + + + + SOFTWARE\JabRef + + + + com.install4j.api.windows.RegistryRoot + HKEY_LOCAL_MACHINE + + + + ${installer:sys.installationDir} + + + Path + + + + + Util.hasFullAdminRights() + + + + + + + SOFTWARE\JabRef + + + + com.install4j.api.windows.RegistryRoot + HKEY_CURRENT_USER + + + + ${installer:sys.installationDir} + + + Path + + + + + !Util.hasFullAdminRights() + + + From 070c53171321e036dbd8f79687626225fd651138 Mon Sep 17 00:00:00 2001 From: hakova Date: Wed, 11 May 2016 01:32:58 -0500 Subject: [PATCH 048/268] Translated the last two entries to Turkish (#1379) --- src/main/resources/l10n/JabRef_tr.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 918e53fed415..71f3c5e3a8f8 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1616,5 +1616,5 @@ Syntax_error_in_regular-expression_pattern=Düzenli_ifade_düzeninde_sözdizimi_ Copy_version_to_clipboard=Sürümü_panoya_kopyala Copied_version_to_clipboard=Sürüm_panoya_kopyalandı -BibTeX_key= -Message= +BibTeX_key=BibTeX_anahtarı +Message=Mesaj From ac08efbf42638ade9a93136999ff61b71510c70f Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 11 May 2016 08:59:17 +0200 Subject: [PATCH 049/268] Remove union merge causing many duplicates --- .gitattributes | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index d8e9a4c73df0..0d611d320583 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,3 @@ gradlew eol=lf # ensure that line endings of *.java and *.properties are normalized *.properties text *.java text - -# ensure that CHANGELOG entries are merged instead of causing conflicts -CHANGELOG.md merge=union From 100f81483d20e054e5a59ef177f61996ef2c9566 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 11 May 2016 09:31:23 +0200 Subject: [PATCH 050/268] Fix #1364 Really fix it :smile: --- jabref.install4j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jabref.install4j b/jabref.install4j index 72037811a59c..f408ec68a156 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -169,7 +169,7 @@ context.setInstallationDirectory(context.getInstallationDirectory()); } else { if (Util.isAtLeastWindowsVista()) { - context.setInstallationDirectory(new File(System.getProperty("LOCALAPPDATA"), "JabRef")); + context.setInstallationDirectory(new File(System.getenv("LOCALAPPDATA"), "JabRef")); } else { context.setInstallationDirectory(new File(System.getProperty("user.home"), "JabRef")); } From 3009bbeb036f431a9679cbfcf7a06268286bf546 Mon Sep 17 00:00:00 2001 From: matthiasgeiger Date: Wed, 11 May 2016 09:44:26 +0200 Subject: [PATCH 051/268] add specific icon for DOIs - implements #696 --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/GUIGlobals.java | 2 +- src/main/java/net/sf/jabref/gui/IconTheme.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2b91e0f3dde..bfb7283b70bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Added an option in the about dialog to easily copy the version information of JabRef - Integrity check table can be sorted by clicking on column headings - Added \SOFTWARE\Jabref 'Path' registry entry for installation path inside the installer +- Added an additional icon to distinguish DOI and URL links ([feature request #696](https://github.com/JabRef/jabref/issues/696)) ### Fixed - Fixed [#473](https://github.com/JabRef/jabref/issues/473): Values in an entry containing symbols like ' are now properly escaped for exporting to the database diff --git a/src/main/java/net/sf/jabref/gui/GUIGlobals.java b/src/main/java/net/sf/jabref/gui/GUIGlobals.java index 2d2623329314..315808a81164 100644 --- a/src/main/java/net/sf/jabref/gui/GUIGlobals.java +++ b/src/main/java/net/sf/jabref/gui/GUIGlobals.java @@ -145,7 +145,7 @@ public static void init() { label.setToolTipText(Localization.lang("Open") + " ArXiv URL"); GUIGlobals.TABLE_ICONS.put("eprint", label); - label = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); + label = new JLabel(IconTheme.JabRefIcon.DOI.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " DOI " + Localization.lang("web link")); GUIGlobals.TABLE_ICONS.put("doi", label); diff --git a/src/main/java/net/sf/jabref/gui/IconTheme.java b/src/main/java/net/sf/jabref/gui/IconTheme.java index 1a159f1ee1b2..5dd4fbf130bd 100644 --- a/src/main/java/net/sf/jabref/gui/IconTheme.java +++ b/src/main/java/net/sf/jabref/gui/IconTheme.java @@ -87,7 +87,7 @@ public enum JabRefIcon { REMOVE_NOBOX("\uf374") /*css: minus */, FILE("\uf214"), /* css: file*/ PDF_FILE("\uf225"), /* css: file-pdf*/ - DOI("\uf59f") /*css: web*/, + DOI("\uF072") /*css: barcode-scan*/, DUPLICATE("\uf191") /*css: content-duplicate */, EDIT("\uf3eb") /*css: pencil */, NEW("\uf224") /* css: file-outline */, From 7d0d4ce10cd534ee0b901fa61d78217b9df04b36 Mon Sep 17 00:00:00 2001 From: Christian Bartsch Date: Wed, 11 May 2016 11:30:48 +0200 Subject: [PATCH 052/268] fix-796 test now finds the entryTable --- .../java/net/sf/jabref/gui/UndoTest.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java b/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java index 907870cc6eb5..06f57d2899c4 100644 --- a/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java +++ b/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java @@ -4,7 +4,6 @@ import net.sf.jabref.JabRefMain; -import org.assertj.swing.finder.JFileChooserFinder; import org.assertj.swing.fixture.FrameFixture; import org.assertj.swing.fixture.JFileChooserFixture; import org.assertj.swing.fixture.JTableFixture; @@ -13,7 +12,6 @@ import static org.assertj.swing.finder.WindowFinder.findFrame; import static org.assertj.swing.launcher.ApplicationLauncher.application; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class UndoTest extends AssertJSwingJUnitTestCase { @@ -42,13 +40,16 @@ private String getTestFilePath(String fileName) { } private void importBibIntoNewDatabase(FrameFixture mainFrame, String path) { - mainFrame.menuItemWithPath("File", "Import into new database").click(); + // have to replace backslashes with normal slashes b/c assertJ can't type the former one on windows + path = path.replace("\\", "/"); - JFileChooserFixture openFileDialog = JFileChooserFinder.findFileChooser().withTimeout(10_000).using(robot()); + mainFrame.menuItemWithPath("File", "Import into new database").click(); + JFileChooserFixture openFileDialog = mainFrame.fileChooser(); robot().settings().delayBetweenEvents(1); openFileDialog.fileNameTextBox().enterText(path); - robot().settings().delayBetweenEvents(50); + robot().settings().delayBetweenEvents(1_000); openFileDialog.approve(); + robot().settings().delayBetweenEvents(50); } @Test @@ -57,14 +58,17 @@ public void undoCutOfMultipleEntries() { importBibIntoNewDatabase(mainFrame, getTestFilePath("testbib/testjabref.bib")); JTableFixture entryTable = mainFrame.table(); + assertTrue("The database must have at least 2 entries for the test to begin!", entryTable.rowCount() >= 2); entryTable.selectRows(0, 1); + entryTable.requireSelectedRows(0, 1); - int rowCount = entryTable.rowCount(); + int oldRowCount = entryTable.rowCount(); mainFrame.menuItemWithPath("Edit", "Cut").click(); mainFrame.menuItemWithPath("Edit", "Undo").click(); - assertEquals(rowCount, entryTable.rowCount()); + entryTable.requireRowCount(oldRowCount); + mainFrame.menuItemWithPath("File", "Close database").click(); mainFrame.menuItemWithPath("File", "Close database").click(); exitJabRef(mainFrame); } From 7ab584c1e333a684d1770fe2b60f0c5dfae23f3d Mon Sep 17 00:00:00 2001 From: Matthias Geiger Date: Wed, 11 May 2016 13:28:03 +0200 Subject: [PATCH 053/268] Update codecov.yml to disable PR comments --- codecov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/codecov.yml b/codecov.yml index 96c12579acb6..29aaa66eedc7 100644 --- a/codecov.yml +++ b/codecov.yml @@ -3,3 +3,4 @@ coverage: - src/gen/.* status: patch: false +comment: off From e988335e84f3c830d33f0b8c5affbbc5d0f56142 Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 12 May 2016 08:26:10 +0200 Subject: [PATCH 054/268] Update Preview Panel on Generate BibtexKey (#1355) Fix for #1353 Use locking with lock try unlock Some formatting Encapsulate frame in getter --- CHANGELOG.md | 1 + .../jabref/gui/DuplicateResolverDialog.java | 2 +- .../sf/jabref/gui/ImportInspectionDialog.java | 361 ++++++++++-------- .../jabref/importer/fetcher/CrossRefTest.java | 10 +- 4 files changed, 200 insertions(+), 174 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfb7283b70bd..ab3b180cd20c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed [#1364](https://github.com/JabRef/jabref/issues/1364): Windows: install to LOCALAPPDATA directory for non-admin users - Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to "[auth][year]" - Fixed [#796](https://github.com/JabRef/jabref/issues/796): Undoing more than one entry at the same time is now working +- Fixed [#1353](https://github.com/JabRef/jabref/issues/1353): Fetch-Preview did not display updated BibTeX-Key after clicking on `Generate Now` ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java b/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java index be6b096e3965..03efbc1d5490 100644 --- a/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java +++ b/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java @@ -68,7 +68,7 @@ public DuplicateResolverDialog(JabRefFrame frame, BibEntry one, BibEntry two, Du public DuplicateResolverDialog(ImportInspectionDialog dialog, BibEntry one, BibEntry two, DuplicateResolverType type) { super(dialog, Localization.lang("Possible duplicate entries"), true); - this.frame = dialog.frame; + this.frame = dialog.getFrame(); init(one, two, type); } diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index ad7376347bf5..b4e1edfc2c78 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -141,73 +141,48 @@ * any more results via addEntry, call entryListComplete() or dispose(), after * receiving this call). */ + public class ImportInspectionDialog extends JDialog implements ImportInspector, OutputPrinter { - private static final Log LOGGER = LogFactory.getLog(ImportInspectionDialog.class); + private static final Log LOGGER = LogFactory.getLog(ImportInspectionDialog.class); private BasePanel panel; - - public final JabRefFrame frame; - + private final JabRefFrame frame; private final BibDatabaseContext bibDatabaseContext; - private final JSplitPane contentPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); - private final JTable glTable; - private final TableComparatorChooser comparatorChooser; - private final DefaultEventSelectionModel selectionModel; - private final JProgressBar progressBar = new JProgressBar(SwingConstants.HORIZONTAL); - private final JButton ok = new JButton(Localization.lang("OK")); private final JButton generate = new JButton(Localization.lang("Generate now")); - private final EventList entries = new BasicEventList<>(); - private final SortedList sortedList; /** * Duplicate resolving may require deletion of old entries. */ private final List entriesToDelete = new ArrayList<>(); - private final String undoName; - private final List callBacks = new ArrayList<>(); - private final boolean newDatabase; - private final JPopupMenu popup = new JPopupMenu(); - private final JButton deselectAllDuplicates = new JButton(Localization.lang("Deselect all duplicates")); - private final JButton stop = new JButton(Localization.lang("Stop")); - private final PreviewPanel preview; - private boolean generatedKeys; // Set to true after keys have been generated. - private boolean defaultSelected = true; - private final Rectangle toRect = new Rectangle(0, 0, 1, 1); - private final Map> groupAdditions = new HashMap<>(); - private final JCheckBox autoGenerate = new JCheckBox(Localization.lang("Generate keys"), Globals.prefs.getBoolean(JabRefPreferences.GENERATE_KEYS_AFTER_INSPECTION)); - private final JLabel duplLabel = new JLabel(IconTheme.JabRefIcon.DUPLICATE.getSmallIcon()); private final JLabel fileLabel = new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon()); private final JLabel urlLabel = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); - private static final List INSPECTION_FIELDS = Arrays.asList("author", "title", "year", BibEntry.KEY_FIELD); - private static final int DUPL_COL = 1; private static final int FILE_COL = 2; private static final int URL_COL = 3; private static final int PAD = 4; - private static final String URL_FIELD = "url"; @@ -284,8 +259,7 @@ public ImportInspectionDialog(JabRefFrame frame, BasePanel panel, String undoNam bb.addGlue(); bb.addButton(ok); bb.addButton(stop); - JButton cancel = new JButton( - Localization.lang("Cancel")); + JButton cancel = new JButton(Localization.lang("Cancel")); bb.addButton(cancel); bb.addRelatedGap(); JButton help = new HelpAction(HelpFiles.IMPORT_INSPECTION).getHelpButton(); @@ -341,8 +315,8 @@ public ImportInspectionDialog(JabRefFrame frame, BasePanel panel, String undoNam getContentPane().add(bb.getPanel(), BorderLayout.SOUTH); // Remember and default to last size: - setSize(new Dimension(Globals.prefs.getInt(JabRefPreferences.IMPORT_INSPECTION_DIALOG_WIDTH), Globals.prefs - .getInt(JabRefPreferences.IMPORT_INSPECTION_DIALOG_HEIGHT))); + setSize(new Dimension(Globals.prefs.getInt(JabRefPreferences.IMPORT_INSPECTION_DIALOG_WIDTH), + Globals.prefs.getInt(JabRefPreferences.IMPORT_INSPECTION_DIALOG_HEIGHT))); addWindowListener(new WindowAdapter() { @Override @@ -413,8 +387,11 @@ public void addEntries(Collection entriesToAdd) { deselectAllDuplicates.setEnabled(true); } this.entries.getReadWriteLock().writeLock().lock(); - this.entries.add(entry); - this.entries.getReadWriteLock().writeLock().unlock(); + try { + this.entries.add(entry); + } finally { + this.entries.getReadWriteLock().writeLock().unlock(); + } } } @@ -438,7 +415,6 @@ private Optional internalDuplicate(Collection entriesDupe, B return Optional.empty(); } - /* (non-Javadoc) * @see net.sf.jabref.gui.ImportInspection#entryListComplete() */ @@ -458,7 +434,6 @@ public void entryListComplete() { } } - /** * Generate key for the selected entry only. */ @@ -468,31 +443,32 @@ private void generateKeySelectedEntry() { } BibEntry entry = selectionModel.getSelected().get(0); entries.getReadWriteLock().writeLock().lock(); + try { + BibDatabase database; + MetaData localMetaData; + + // Relate to existing database, if any: + if (panel == null) { + database = new BibDatabase(); + localMetaData = new MetaData(); + } else { + database = panel.getDatabase(); + localMetaData = panel.getBibDatabaseContext().getMetaData(); + } - BibDatabase database; - MetaData localMetaData; + entry.setId(IdGenerator.next()); + // Add the entry to the database we are working with: + database.insertEntry(entry); - // Relate to existing database, if any: - if (panel == null) { - database = new BibDatabase(); - localMetaData = new MetaData(); - } else { - database = panel.getDatabase(); - localMetaData = panel.getBibDatabaseContext().getMetaData(); + // Generate a unique key: + LabelPatternUtil.makeLabel(localMetaData, database, entry); + // Remove the entry from the database again, since we only added it in + // order to + // make sure the key was unique: + database.removeEntry(entry); + } finally { + entries.getReadWriteLock().writeLock().unlock(); } - - entry.setId(IdGenerator.next()); - // Add the entry to the database we are working with: - database.insertEntry(entry); - - // Generate a unique key: - LabelPatternUtil.makeLabel(localMetaData, database, entry); - // Remove the entry from the database again, since we only added it in - // order to - // make sure the key was unique: - database.removeEntry(entry); - - entries.getReadWriteLock().writeLock().lock(); glTable.repaint(); } @@ -503,41 +479,48 @@ private void generateKeySelectedEntry() { */ private void generateKeys() { entries.getReadWriteLock().writeLock().lock(); + try { - BibDatabase database; - MetaData localMetaData; + BibDatabase database; + MetaData localMetaData; - // Relate to existing database, if any: - if (panel == null) { - database = new BibDatabase(); - localMetaData = new MetaData(); - } else { - database = panel.getDatabase(); - localMetaData = panel.getBibDatabaseContext().getMetaData(); - } + // Relate to existing database, if any: + if (panel == null) { + database = new BibDatabase(); + localMetaData = new MetaData(); + } else { + database = panel.getDatabase(); + localMetaData = panel.getBibDatabaseContext().getMetaData(); + } - List keys = new ArrayList<>(entries.size()); - // Iterate over the entries, add them to the database we are working - // with, - // and generate unique keys: - for (BibEntry entry : entries) { + List keys = new ArrayList<>(entries.size()); + // Iterate over the entries, add them to the database we are working + // with, + // and generate unique keys: + for (BibEntry entry : entries) { - entry.setId(IdGenerator.next()); - database.insertEntry(entry); + entry.setId(IdGenerator.next()); + database.insertEntry(entry); - LabelPatternUtil.makeLabel(localMetaData, database, entry); - // Add the generated key to our list: - keys.add(entry.getCiteKey()); - } - // Remove the entries from the database again, since they are not - // supposed to - // added yet. They only needed to be in it while we generated the keys, - // to keep - // control over key uniqueness. - for (BibEntry entry : entries) { - database.removeEntry(entry); + LabelPatternUtil.makeLabel(localMetaData, database, entry); + // Add the generated key to our list: + keys.add(entry.getCiteKey()); + } + + preview.update(); + preview.repaint(); + // Remove the entries from the database again, since they are not + // supposed to + // added yet. They only needed to be in it while we generated the keys, + // to keep + // control over key uniqueness. + for (BibEntry entry : entries) { + database.removeEntry(entry); + } + } finally { + entries.getReadWriteLock().writeLock().unlock(); } - entries.getReadWriteLock().writeLock().lock(); + glTable.repaint(); } @@ -580,6 +563,7 @@ private AbstractAction getAction(GroupTreeNode node) { return action; } + /** * Stores the information about the selected entries being scheduled for * addition to this group. The entries are *not* added to the group at this @@ -590,6 +574,7 @@ class AddToGroupAction extends AbstractAction { private final GroupTreeNode node; + public AddToGroupAction(GroupTreeNode node) { super(node.getName()); this.node = node; @@ -599,26 +584,31 @@ public AddToGroupAction(GroupTreeNode node) { public void actionPerformed(ActionEvent event) { selectionModel.getSelected().getReadWriteLock().writeLock().lock(); - for (BibEntry entry : selectionModel.getSelected()) { - // We store the groups this entry should be added to in a Set in - // the Map: - Set groups = groupAdditions.get(entry); - if (groups == null) { - // No previous definitions, so we create the Set now: - groups = new HashSet<>(); - groupAdditions.put(entry, groups); + try { + for (BibEntry entry : selectionModel.getSelected()) { + // We store the groups this entry should be added to in a Set in + // the Map: + Set groups = groupAdditions.get(entry); + if (groups == null) { + // No previous definitions, so we create the Set now: + groups = new HashSet<>(); + groupAdditions.put(entry, groups); + } + // Add the group: + groups.add(node); } - // Add the group: - groups.add(node); + } finally { + selectionModel.getSelected().getReadWriteLock().writeLock().unlock(); } - selectionModel.getSelected().getReadWriteLock().writeLock().unlock(); } } + public void addCallBack(CallBack cb) { callBacks.add(cb); } + private class OkListener implements ActionListener { @Override @@ -642,10 +632,11 @@ public void actionPerformed(ActionEvent event) { // is indicated by the entry's group hit status: if (entry.isGroupHit()) { CheckBoxMessage cbm = new CheckBoxMessage( - Localization.lang("There are possible duplicates (marked with an icon) that haven't been resolved. Continue?"), + Localization + .lang("There are possible duplicates (marked with an icon) that haven't been resolved. Continue?"), Localization.lang("Disable this confirmation dialog"), false); - int answer = JOptionPane.showConfirmDialog(ImportInspectionDialog.this, - cbm, Localization.lang("Duplicates found"), JOptionPane.YES_NO_OPTION); + int answer = JOptionPane.showConfirmDialog(ImportInspectionDialog.this, cbm, + Localization.lang("Duplicates found"), JOptionPane.YES_NO_OPTION); if (cbm.isSelected()) { Globals.prefs.putBoolean(JabRefPreferences.WARN_ABOUT_DUPLICATES_IN_INSPECTION, false); } @@ -707,7 +698,8 @@ private void removeEntriesToDelete(NamedCompound ce) { private void addSelectedEntries(NamedCompound ce, final List selected) { if (newDatabase) { // Create a new BasePanel for the entries: - Defaults defaults = new Defaults(BibDatabaseMode.fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); + Defaults defaults = new Defaults(BibDatabaseMode + .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); panel = new BasePanel(frame, new BibDatabaseContext(defaults), Globals.prefs.getDefaultEncoding()); } @@ -741,7 +733,6 @@ private void addSelectedEntries(NamedCompound ce, final List selected) groupingCanceled = addToGroups(ce, entry, groups); } - entry.setId(IdGenerator.next()); panel.getDatabase().insertEntry(entry); ce.addEdit(new UndoableInsertEntry(panel.getDatabase(), entry, panel)); @@ -760,11 +751,9 @@ private boolean addToGroups(NamedCompound ce, BibEntry entry, Set // The best course of action is probably to ask the // user if a key should be generated // immediately. - int answer = JOptionPane - .showConfirmDialog( - ImportInspectionDialog.this, - Localization.lang("Cannot add entries to group without generating keys. Generate keys now?"), - Localization.lang("Add to group"), JOptionPane.YES_NO_OPTION); + int answer = JOptionPane.showConfirmDialog(ImportInspectionDialog.this, + Localization.lang("Cannot add entries to group without generating keys. Generate keys now?"), + Localization.lang("Add to group"), JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.YES_OPTION) { generateKeys(); } else { @@ -808,6 +797,7 @@ private List getSelectedEntries() { } + private void signalStopFetching() { callBacks.forEach(CallBack::stopFetching); } @@ -830,6 +820,7 @@ private void setWidths() { } } + private class DeleteListener extends AbstractAction { public DeleteListener() { @@ -849,11 +840,15 @@ private void removeSelectedEntries() { int row = glTable.getSelectedRow(); List toRemove = new ArrayList<>(); toRemove.addAll(selectionModel.getSelected()); + entries.getReadWriteLock().writeLock().lock(); - for (Object o : toRemove) { - entries.remove(o); + try { + for (Object o : toRemove) { + entries.remove(o); + } + } finally { + entries.getReadWriteLock().writeLock().unlock(); } - entries.getReadWriteLock().writeLock().unlock(); glTable.clearSelection(); if ((row >= 0) && (!entries.isEmpty())) { row = Math.min(entries.size() - 1, row); @@ -866,6 +861,7 @@ private class SelectionButton implements ActionListener { private final Boolean enable; + public SelectionButton(boolean enable) { this.enable = enable; } @@ -916,9 +912,8 @@ public void mouseClicked(MouseEvent e) { return; } FileListEntry fl = tableModel.getEntry(0); - (new ExternalFileMenuItem(frame, entry, "", fl.link, null, - panel.getBibDatabaseContext(), fl.type)) - .actionPerformed(null); + (new ExternalFileMenuItem(frame, entry, "", fl.link, null, panel.getBibDatabaseContext(), + fl.type)).actionPerformed(null); } } else { // Must be URL_COL openExternalLink(URL_FIELD, e); @@ -1029,7 +1024,8 @@ public void mousePressed(MouseEvent e) { // Is this the duplicate icon column, and is there an icon? if ((col == DUPL_COL) && (glTable.getValueAt(row, col) != null)) { BibEntry first = sortedList.get(row); - Optional other = DuplicateCheck.containsDuplicate(panel.getDatabase(), first, panel.getBibDatabaseContext().getMode()); + Optional other = DuplicateCheck.containsDuplicate(panel.getDatabase(), first, + panel.getBibDatabaseContext().getMode()); if (other.isPresent()) { // This will be true if the duplicate is in the existing // database. @@ -1046,20 +1042,30 @@ public void mousePressed(MouseEvent e) { // Clear duplicate icon, which is controlled by the // group hit // field of the entry: + entries.getReadWriteLock().writeLock().lock(); - first.setGroupHit(false); - entries.getReadWriteLock().writeLock().unlock(); + try { + first.setGroupHit(false); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } } else if (diag.getSelected() == DuplicateResolverResult.KEEP_LOWER) { // Remove the entry from the import inspection dialog. entries.getReadWriteLock().writeLock().lock(); - entries.remove(first); - entries.getReadWriteLock().writeLock().unlock(); + try { + entries.remove(first); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } } else if (diag.getSelected() == DuplicateResolverResult.KEEP_BOTH) { // Do nothing. entries.getReadWriteLock().writeLock().lock(); - first.setGroupHit(false); - entries.getReadWriteLock().writeLock().unlock(); + try { + first.setGroupHit(false); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } } else if (diag.getSelected() == DuplicateResolverResult.KEEP_MERGE) { // Remove old entry. Or... add it to a list of entries // to be deleted. We only delete @@ -1070,12 +1076,15 @@ public void mousePressed(MouseEvent e) { // group hit // field of the entry: entries.getReadWriteLock().writeLock().lock(); - diag.getMergedEntry().setGroupHit(false); - diag.getMergedEntry().setSearchHit(true); - entries.add(diag.getMergedEntry()); - entries.remove(first); - first = new BibEntry(); // Reset first so the next duplicate doesn't trigger - entries.getReadWriteLock().writeLock().unlock(); + try { + diag.getMergedEntry().setGroupHit(false); + diag.getMergedEntry().setSearchHit(true); + entries.add(diag.getMergedEntry()); + entries.remove(first); + first = new BibEntry(); // Reset first so the next duplicate doesn't trigger + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } } } // Check if the duplicate is of another entry in the import: @@ -1122,23 +1131,26 @@ public void actionPerformed(ActionEvent event) { String result = JOptionPane.showInputDialog(ImportInspectionDialog.this, Localization.lang("Enter URL"), entry.getField(URL_FIELD)); entries.getReadWriteLock().writeLock().lock(); - if (result != null) { - if (result.isEmpty()) { - entry.clearField(URL_FIELD); - } else { - entry.setField(URL_FIELD, result); + try { + if (result != null) { + if (result.isEmpty()) { + entry.clearField(URL_FIELD); + } else { + entry.setField(URL_FIELD, result); + } } + } finally { + entries.getReadWriteLock().writeLock().unlock(); } - entries.getReadWriteLock().writeLock().unlock(); glTable.repaint(); } } - class DownloadFile extends JMenuItem implements ActionListener, - DownloadExternalFile.DownloadCallback { + class DownloadFile extends JMenuItem implements ActionListener, DownloadExternalFile.DownloadCallback { private BibEntry entry; + public DownloadFile() { super(Localization.lang("Download file")); addActionListener(this); @@ -1154,8 +1166,7 @@ public void actionPerformed(ActionEvent actionEvent) { if (bibtexKey == null) { int answer = JOptionPane.showConfirmDialog(frame, Localization.lang("This entry has no BibTeX key. Generate key now?"), - Localization.lang("Download file"), JOptionPane.OK_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE); + Localization.lang("Download file"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (answer == JOptionPane.OK_OPTION) { generateKeySelectedEntry(); bibtexKey = entry.getCiteKey(); @@ -1176,8 +1187,11 @@ public void downloadComplete(FileListEntry file) { entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(localModel::setContent); localModel.addEntry(localModel.getRowCount(), file); entries.getReadWriteLock().writeLock().lock(); - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); - entries.getReadWriteLock().writeLock().unlock(); + try { + entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } glTable.repaint(); } } @@ -1198,8 +1212,7 @@ public void actionPerformed(ActionEvent actionEvent) { if (entry.getCiteKey() == null) { int answer = JOptionPane.showConfirmDialog(frame, Localization.lang("This entry has no BibTeX key. Generate key now?"), - Localization.lang("Download file"), JOptionPane.OK_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE); + Localization.lang("Download file"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (answer == JOptionPane.OK_OPTION) { generateKeySelectedEntry(); } else { @@ -1214,21 +1227,25 @@ public void actionPerformed(ActionEvent actionEvent) { JabRefExecutorService.INSTANCE.execute( net.sf.jabref.external.AutoSetLinks.autoSetLinks(entry, localModel, bibDatabaseContext, e -> { if (e.getID() > 0) { + entries.getReadWriteLock().writeLock().lock(); - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); - entries.getReadWriteLock().writeLock().unlock(); + try { + entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } glTable.repaint(); } - } , diag)); + }, diag)); } } - private class LinkLocalFile extends JMenuItem implements ActionListener, - DownloadExternalFile.DownloadCallback { + private class LinkLocalFile extends JMenuItem implements ActionListener, DownloadExternalFile.DownloadCallback { private BibEntry entry; + public LinkLocalFile() { super(Localization.lang("Link local file")); addActionListener(this); @@ -1248,8 +1265,11 @@ public void actionPerformed(ActionEvent actionEvent) { entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(localModel::setContent); localModel.addEntry(localModel.getRowCount(), flEntry); entries.getReadWriteLock().writeLock().lock(); - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); - entries.getReadWriteLock().writeLock().unlock(); + try { + entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } glTable.repaint(); } } @@ -1261,12 +1281,16 @@ public void downloadComplete(FileListEntry file) { entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(localModel::setContent); localModel.addEntry(localModel.getRowCount(), file); entries.getReadWriteLock().writeLock().lock(); - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); - entries.getReadWriteLock().writeLock().unlock(); + try { + entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } glTable.repaint(); } } + private void setupComparatorChooser() { // First column: @@ -1294,19 +1318,12 @@ private void setupComparatorChooser() { comparators.add(new FieldComparator(INSPECTION_FIELDS.get(i - PAD))); } - // Set initial sort columns: - - /* - * // Default sort order: String[] sortFields = new String[] - * {Globals.prefs.get(JabRefPreferences.PRIMARY_SORT_FIELD), Globals.prefs.get(JabRefPreferences.SECONDARY_SORT_FIELD), - * Globals.prefs.get(JabRefPreferences.TERTIARY_SORT_FIELD)}; boolean[] sortDirections = new - * boolean[] {Globals.prefs.getBoolean(JabRefPreferences.PRIMARY_SORT_DESCENDING), - * Globals.prefs.getBoolean(JabRefPreferences.SECONDARY_SORT_DESCENDING), - * Globals.prefs.getBoolean(JabRefPreferences.TERTIARY_SORT_DESCENDING)}; // descending - */ sortedList.getReadWriteLock().writeLock().lock(); - comparatorChooser.appendComparator(PAD, 0, false); - sortedList.getReadWriteLock().writeLock().unlock(); + try { + comparatorChooser.appendComparator(PAD, 0, false); + } finally { + sortedList.getReadWriteLock().writeLock().unlock(); + } } @@ -1338,6 +1355,7 @@ class EntryTable extends JTable { private final GeneralRenderer renderer = new GeneralRenderer(Color.white); + public EntryTable(TableModel model) { super(model); getTableHeader().setReorderingAllowed(false); @@ -1369,9 +1387,12 @@ public void setValueAt(Object value, int row, int column) { // Only column 0, which is controlled by BibEntry.searchHit, is // editable: entries.getReadWriteLock().writeLock().lock(); - BibEntry entry = sortedList.get(row); - entry.setSearchHit((Boolean) value); - entries.getReadWriteLock().writeLock().unlock(); + try { + BibEntry entry = sortedList.get(row); + entry.setSearchHit((Boolean) value); + } finally { + entries.getReadWriteLock().writeLock().unlock(); + } } } @@ -1426,8 +1447,7 @@ public Object getColumnValue(BibEntry entry, int i) { } else { String field = INSPECTION_FIELDS.get(i - PAD); if (InternalBibtexFields.getFieldExtras(field).contains(FieldProperties.PERSON_NAMES)) { - return entry.getFieldOptional(field).map(AuthorList::fixAuthorNatbib) - .orElse(""); + return entry.getFieldOptional(field).map(AuthorList::fixAuthorNatbib).orElse(""); } else { return entry.getField(field); } @@ -1436,6 +1456,7 @@ public Object getColumnValue(BibEntry entry, int i) { } + @Override public void setStatus(String s) { frame.setStatus(s); @@ -1450,4 +1471,8 @@ public void showMessage(Object message, String title, int msgType) { public void showMessage(String message) { JOptionPane.showMessageDialog(this, message); } + + public JabRefFrame getFrame() { + return frame; + } } diff --git a/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java b/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java index a97ca9454a96..c826d0203f22 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java @@ -10,7 +10,7 @@ public class CrossRefTest { @Test - public void findExactData() throws Exception { + public void findExactData() { BibEntry entry = new BibEntry(); entry.setField("title", "Service Interaction Patterns"); entry.setField("author", "Barros, Alistair and Dumas, Marlon and Arthur H.M. ter Hofstede"); @@ -19,7 +19,7 @@ public void findExactData() throws Exception { } @Test - public void findMissingAuthor() throws Exception { + public void findMissingAuthor() { BibEntry entry = new BibEntry(); entry.setField("title", "Towards Application Portability in Platform as a Service"); entry.setField("author", "Stefan Kolb"); @@ -27,14 +27,14 @@ public void findMissingAuthor() throws Exception { } @Test - public void findTitleOnly() throws Exception { + public void findTitleOnly() { BibEntry entry = new BibEntry(); entry.setField("title", "Towards Application Portability in Platform as a Service"); assertEquals("10.1109/sose.2014.26", CrossRef.findDOI(entry).get().getDOI().toLowerCase(Locale.ENGLISH)); } @Test - public void findIncompleteTitle() throws Exception { + public void findIncompleteTitle() { BibEntry entry = new BibEntry(); entry.setField("title", "Towards Application Portability"); entry.setField("author", "Stefan Kolb and Guido Wirtz"); @@ -42,7 +42,7 @@ public void findIncompleteTitle() throws Exception { } @Test - public void findWrongAuthor() throws Exception { + public void findWrongAuthor() { BibEntry entry = new BibEntry(); entry.setField("title", "Towards Application Portability in Platform as a Service"); entry.setField("author", "Stefan Kolb and Simon Harrer"); From 771db07ceb627f1517399fa2420b6abbf24942b4 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 12 May 2016 15:23:03 +0200 Subject: [PATCH 055/268] Fix #1357 sort issue --- .../sf/jabref/gui/SaveOrderConfigDisplay.java | 1 + .../DatabasePropertiesDialog.java | 22 +++++-------------- .../jabref/logic/config/SaveOrderConfig.java | 6 +++++ 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java b/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java index 1892b312807c..00c0f63f7828 100644 --- a/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java +++ b/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java @@ -116,6 +116,7 @@ public SaveOrderConfig getSaveOrderConfig() { saveOrderConfig.sortCriteria[1].descending = saveSecDesc.isSelected(); saveOrderConfig.sortCriteria[2].field = getSelectedItemAsLowerCaseTrim(saveTerSort); saveOrderConfig.sortCriteria[2].descending = saveTerDesc.isSelected(); + return saveOrderConfig; } diff --git a/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java b/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java index fefb620ad038..a5881cc73c1f 100644 --- a/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java +++ b/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java @@ -52,13 +52,6 @@ import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; -/** - * Created by IntelliJ IDEA. - * User: alver - * Date: Oct 31, 2005 - * Time: 10:46:03 PM - * To change this template use File | Settings | File Templates. - */ public class DatabasePropertiesDialog extends JDialog { private MetaData metaData; @@ -71,10 +64,10 @@ public class DatabasePropertiesDialog extends JDialog { private String oldFileVal = ""; private String oldFileIndvVal = ""; private SaveOrderConfig oldSaveOrderConfig; - private SaveOrderConfig defaultSaveOrderConfig; /* The code for "Save sort order" is copied from FileSortTab and slightly updated to fit storing at metadata */ private JRadioButton saveInOriginalOrder; + private JRadioButton saveInSpecifiedOrder; private final JCheckBox protect = new JCheckBox( @@ -150,7 +143,6 @@ private void init(JFrame parent) { pack(); AbstractAction closeAction = new AbstractAction() { - @Override public void actionPerformed(ActionEvent e) { dispose(); @@ -196,14 +188,11 @@ public void setVisible(boolean visible) { private void setValues() { encoding.setSelectedItem(panel.getEncoding()); - defaultSaveOrderConfig = new SaveOrderConfig(); - defaultSaveOrderConfig.setSaveInOriginalOrder(); - Optional storedSaveOrderConfig = metaData.getSaveOrderConfig(); boolean selected; if (!storedSaveOrderConfig.isPresent()) { saveInOriginalOrder.setSelected(true); - oldSaveOrderConfig = null; + oldSaveOrderConfig = SaveOrderConfig.getDefaultSaveOrder(); selected = false; } else { SaveOrderConfig saveOrderConfig = storedSaveOrderConfig.get(); @@ -266,10 +255,11 @@ private void storeSettings() { metaData.markAsNotProtected(); } - SaveOrderConfig newSaveOrderConfig = saveOrderPanel.getSaveOrderConfig(); + SaveOrderConfig newSaveOrderConfig; if (saveInOriginalOrder.isSelected()) { - newSaveOrderConfig.setSaveInOriginalOrder(); + newSaveOrderConfig = SaveOrderConfig.getDefaultSaveOrder(); } else { + newSaveOrderConfig = saveOrderPanel.getSaveOrderConfig(); newSaveOrderConfig.setSaveInSpecifiedOrder(); } @@ -282,7 +272,7 @@ private void storeSettings() { } if (saveOrderConfigChanged) { - if (newSaveOrderConfig.equals(defaultSaveOrderConfig)) { + if (newSaveOrderConfig.equals(SaveOrderConfig.getDefaultSaveOrder())) { metaData.clearSaveOrderConfig(); } else { metaData.setSaveOrderConfig(newSaveOrderConfig); diff --git a/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java b/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java index 16ee6bade830..7c5efb06ef36 100644 --- a/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java +++ b/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java @@ -206,4 +206,10 @@ public List getConfigurationList() { return res; } + public static SaveOrderConfig getDefaultSaveOrder() { + SaveOrderConfig standard = new SaveOrderConfig(); + standard.setSaveInOriginalOrder(); + return standard; + } + } From 09dfe619170764a6aec092d16d73c7b5589c5e0e Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 12 May 2016 15:23:22 +0200 Subject: [PATCH 056/268] Fix #1381 File links containing blanks are broken if non-default viewer is set * Fix #1381 File links containing blanks are broken if non-default viewer is set * Consistently use ProcessBuilder instead of Runtime.exec --- CHANGELOG.md | 1 + .../net/sf/jabref/gui/desktop/os/Windows.java | 20 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3b180cd20c..c1eb79fb6d73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to "[auth][year]" - Fixed [#796](https://github.com/JabRef/jabref/issues/796): Undoing more than one entry at the same time is now working - Fixed [#1353](https://github.com/JabRef/jabref/issues/1353): Fetch-Preview did not display updated BibTeX-Key after clicking on `Generate Now` +- Fixed [#1381](https://github.com/JabRef/jabref/issues/1381): File links containing blanks are broken if non-default viewer is set ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java b/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java index 3fe266e56f05..d9681297cb5f 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java +++ b/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java @@ -9,26 +9,23 @@ import net.sf.jabref.external.ExternalFileTypes; public class Windows implements NativeDesktop { - private static String DEFAULT_EXECUTABLE_EXTENSION = ".exe"; - @Override public void openFile(String filePath, String fileType) throws IOException { Optional type = ExternalFileTypes.getInstance().getExternalFileTypeByExt(fileType); + if (type.isPresent() && !type.get().getOpenWithApplication().isEmpty()) { openFileWithApplication(filePath, type.get().getOpenWithApplication()); } else { // quote String so explorer handles URL query strings correctly String quotePath = "\"" + filePath +"\""; - Runtime.getRuntime().exec(new String[] {"explorer.exe", quotePath}); + new ProcessBuilder("explorer.exe", quotePath).start(); } - } @Override public String detectProgramPath(String programName, String directoryName) { - String progFiles = System.getenv("ProgramFiles(x86)"); if (progFiles == null) { progFiles = System.getenv("ProgramFiles"); @@ -41,21 +38,18 @@ public String detectProgramPath(String programName, String directoryName) { @Override public void openFileWithApplication(String filePath, String application) throws IOException { - Runtime.getRuntime().exec(Paths.get(application) + " " + Paths.get(filePath)); + new ProcessBuilder(Paths.get(application).toString(), Paths.get(filePath).toString()).start(); } @Override public void openFolderAndSelectFile(String filePath) throws IOException { - String cmd = "explorer.exe"; - String arg = "/select,"; - String[] commandWithArgs = {cmd, arg, filePath}; - //Array variant, because otherwise the Tokenizer, which is internally run, kills the whitespaces in the path - Runtime.getRuntime().exec(commandWithArgs); + new ProcessBuilder("explorer.exe", "/select,", filePath).start(); } @Override public void openConsole(String absolutePath) throws IOException { - - Runtime.getRuntime().exec("cmd.exe /c start", null, new File(absolutePath)); + ProcessBuilder process = new ProcessBuilder("cmd.exe", "/c", "start"); + process.directory(new File(absolutePath)); + process.start(); } } From 661051d5fe5cea0ab9e8f7a753e0d9a7f0a89a3e Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 12 May 2016 16:44:10 +0200 Subject: [PATCH 057/268] Small improvements for page normalizer (#1376) * Small improvements for page normalizer * Make test names consistent * Use Guava string helper --- .../bibtexfields/NormalizePagesFormatter.java | 21 ++++++++++++------- .../NormalizePagesFormatterTest.java | 19 +++++++++++++++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java index 6fb2c3561c99..baf3bd0b359c 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatter.java @@ -7,6 +7,8 @@ import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.l10n.Localization; +import com.google.common.base.Strings; + /** * This class includes sensible defaults for consistent formatting of BibTex page numbers. * @@ -18,10 +20,11 @@ */ public class NormalizePagesFormatter implements Formatter { - private static final Pattern PAGES_DETECT_PATTERN = Pattern.compile("\\A(\\d+)-{1,2}(\\d+)\\Z"); + private static final Pattern PAGES_DETECT_PATTERN = Pattern.compile("\\A(\\d+)(?:-{1,2}(\\d+))?\\Z"); private static final String REJECT_LITERALS = "[^a-zA-Z0-9,\\-\\+,]"; private static final String PAGES_REPLACE_PATTERN = "$1--$2"; + private static final String SINGLE_PAGE_REPLACE_PATTERN = "$1"; @Override @@ -57,17 +60,21 @@ public String format(String value) { return value; } + // Remove pages prefix + String cleanValue = value.replace("pp.", "").replace("p.",""); // remove unwanted literals incl. whitespace - String cleanValue = value.replaceAll("\u2013|\u2014", "-").replaceAll(REJECT_LITERALS, ""); + cleanValue = cleanValue.replaceAll("\u2013|\u2014", "-").replaceAll(REJECT_LITERALS, ""); // try to find pages pattern Matcher matcher = PAGES_DETECT_PATTERN.matcher(cleanValue); - // replace - String newValue = matcher.replaceFirst(PAGES_REPLACE_PATTERN); - // replacement? if(matcher.matches()) { - // write field - return newValue; + // replace + if(Strings.isNullOrEmpty(matcher.group(2))) { + return matcher.replaceFirst(SINGLE_PAGE_REPLACE_PATTERN); + } else { + return matcher.replaceFirst(PAGES_REPLACE_PATTERN); + } } + // no replacement return value; } diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java index 3af98a853c46..0d2ecd85bfab 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java @@ -35,6 +35,11 @@ public void ignoreWhitespaceInPageNumbers() { expectCorrect(" 1 - 2 ", "1--2"); } + @Test + public void removeWhitespaceForSinglePageNumber() { + expectCorrect(" 1 ", "1"); + } + @Test public void ignoreWhitespaceInPageNumbersWithDoubleDash() { expectCorrect("43 -- 103", "43--103"); @@ -56,15 +61,25 @@ public void formatPageNumbersRegexNotMatching() { } @Test - public void doesNotRemoveLetters() { + public void doNotRemoveLetters() { expectCorrect("R1-R50", "R1-R50"); } @Test - public void replacesLongDashWithDoubleDash() { + public void replaceLongDashWithDoubleDash() { expectCorrect("1 \u2014 50", "1--50"); } + @Test + public void removePagePrefix() { + expectCorrect("p.50", "50"); + } + + @Test + public void removePagesPrefix() { + expectCorrect("pp.50", "50"); + } + @Test public void formatExample() { expectCorrect(formatter.getExampleInput(), "1--2"); From 327b16452a83377e24e7966fedc1d3fc87d2b224 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 12 May 2016 17:03:05 +0200 Subject: [PATCH 058/268] Fix #655 Add new OS icons in all required sizes and dephts for Win and Mac --- jabref.install4j | 12 +++++------- src/main/resources/icons/jabref.icns | Bin 0 -> 119529 bytes src/main/resources/icons/jabref.ico | Bin 0 -> 35313 bytes .../resources/images/icons/JabRef-Logo.icns | Bin 194699 -> 0 bytes .../images/icons/JabRef-icon-mac.icns | Bin 130759 -> 0 bytes src/main/resources/images/icons/JabRef.ico | Bin 15086 -> 0 bytes 6 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 src/main/resources/icons/jabref.icns create mode 100644 src/main/resources/icons/jabref.ico delete mode 100644 src/main/resources/images/icons/JabRef-Logo.icns delete mode 100644 src/main/resources/images/icons/JabRef-icon-mac.icns delete mode 100644 src/main/resources/images/icons/JabRef.ico diff --git a/jabref.install4j b/jabref.install4j index f408ec68a156..c8284af3a30d 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -58,8 +58,8 @@ - - + + @@ -86,9 +86,7 @@ - - - + @@ -461,7 +459,7 @@ return true; - ./src/main/resources/images/icons/JabRef-icon-mac.icns + ./src/main/resources/icons/jabref.icns @@ -475,7 +473,7 @@ return true; - ./src/main/resources/images/icons/JabRef-icon.png + ./src/main/resources/icons/jabref.ico diff --git a/src/main/resources/icons/jabref.icns b/src/main/resources/icons/jabref.icns new file mode 100644 index 0000000000000000000000000000000000000000..2e0615d160ec6d763cc2412600263886e94d4746 GIT binary patch literal 119529 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

    ^AyeT-*tyZtd< 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/images/icons/JabRef-Logo.icns b/src/main/resources/images/icons/JabRef-Logo.icns deleted file mode 100644 index 85a4e0acbc2de1b5cbc1fdd3bbada9c626f5d861..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194699 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

    m#^Kz;daNqOPf4UB76b7hO>y)3nXuO){Y%q$Ke5 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 DvdfS* diff --git a/src/main/resources/images/icons/JabRef-icon-mac.icns b/src/main/resources/images/icons/JabRef-icon-mac.icns deleted file mode 100644 index b5d6fae72a551bb73f9942b3a0007a69bd61913e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130759 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 diff --git a/src/main/resources/images/icons/JabRef.ico b/src/main/resources/images/icons/JabRef.ico deleted file mode 100644 index 21cb4433baf05305ece225e1c519ba0c87b45d8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeHO=XVsz5nn(154b;pFMiJ-?~^~@e_;Cp_Hk#MBZoVJkDQMKk?uf%B#=Nk2NaM{ zKnR2)NGPY(O1rC!av%thfby?;r$;lR+0{r|VLzLGZ#0^n?yjn?>gw*Q-`H%wvHjNe z>8Cc_SJ{$&Z?pZ;X0xqYr96LPv$^owC%E(bEx)tb0#M-(sDmc9wYd0qE+F3Q$pj_jh$tLLaNE}SZIv#9L$Ey}rZh2l@{r;u&m zEUK@ijBnJz?er)wi`*UU;QxkYdg1%F(4+ip>S%2yM@tj6H#d^Kv7Xu*>eQ>Xu7>g= zLg@1PFD>_LRfgcrU(SaLh;)Ya*rrphwV`N9&NTNi&Om%WW#?QP_=w^CTp1Z z?Q^C_hArCy9%uiL4};L&|vc#!3OjQv`94%zlCHCC2-d{i@hlrp#3&su38ymbw=R##Ae zPZ#xdyM^wB?Lv;ma<-elSn9_LEpK&_&m1LZTdU5`@|?K#{XcxuhP~H4xJys_dT5}x zTgbq6+t=mBymL@E{D?Q2e*GPMv^;q{=V#eR!Ox~&KI4=Ay_g#`*x!e%SCIj7^mydR zyLr`TTfg!T8!k?b6YC7G7oCbO@-g4N(MkAeFAahBp{M;cG{7?SK?cat+av5LaP7+5 zjh459sB6OSdHgJ|7p+u$E5R%Oj@l|38GK5^g99}DbO18+dt`tvc@kE=y0O$?gA8m_VY}Ap>aG;8X8k4y9MbubLB*HHpZHP7 z(>Uz>`Lij#42mw2Pao3NHKVgqzcK%E9!g)xYf{2V{dvIISW7RSKNB)M7kZdf?WxDn zO4ol_V9x%5ERbHlcrIjk@ysKK)}97?yD0Viab260 z;Mdq^3izKKgHM4^WZ%wyo!6$MQwQhqQgtUCGQ6Od&pmRmJ$ZD&^Lm0NVNc~5$#iAC zwKI#6m!&+XVax<=tzU!;tQWKX5@A=}SZn8W!7_N}h4fEsYexTN)|WqiW4o9eL-Q_LVc8`#HjP~*(Bzq;#1Pj9kWC~_1sbD zqe<;UJGaw+`N>ir3-RddeQn_#ntrL+G>@a=xSI3LVr?r z*5PX*!?f^AMwi6y`ISY;AapT{F)j1Sf5M49^kQ;M)gAZ4HaIf_{lO09e7b`< z?Js_f{q)+KCF{ETd&p3h8tavAR^Vxx!F=Z;WtO@VHpp_o4xM$?ba|b%n7NU+g`Nu| zgLOO`A2NPDY07_o=p|zLv_+NS9qdocqgm={X=4S%&9$$s+zXE4uUW<+G z{qdZHed7##!$KwTNL*oon&F4wwwPn(s8? zd+q^CVHG#QW5#Q1DXiSB)nDkHyRimwVUFh`7LIry#}>@maEy@S%$~Tn67xn5 zsRQ^bv-(zkO919T7Liu~4>`dX=Jm&G@>5sGyu1VJEn^uNE@$myNnYGJrpa+TE$>kW zw$UW;S6tq|f2YeEv{n=^c^{n@dP(%D{ljs2?SAPxFfq@^N3~VdxT~vS>GAGt;L2F% z#^L}zRFxg)gDzljjD_RHY$Ke@QtQHpSp7c(Ia(QGGxn{GqgSNI>t4UaoU235j`yHe zX&LKr>~R+P4s8)}Y{cRF;e#cXF$EZtaqM;64K*Sbmww@d`p($rVxF&V{7S_6`TVfd z@mmbN|L3~Kc)*8#<~Rk1C05~*af;9It(md-OGkVLzk_dWVvjS9%lp}$@dbBq=HYLA zB<=e+U+@`(zklKHUicdkv-5QHksad9mmd+Vwhe@zC_sLUaiP)JtKz8 z_RH7s%^1tidlW9bZj>ZN>3GueSBMygEOIS-lA9s=8t!&cnvZw^ue)r&@{;Q?KZp47 PtgYpj|2O)B#XkQVdQ*}+ From bab82ab8ab270841fbe8e9ef630c9de374eeb12a Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Thu, 12 May 2016 17:19:42 +0200 Subject: [PATCH 059/268] Sourceforge is deprecated --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1eb79fb6d73..a57ce7ae5c6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,7 @@ Here, the categories "Changed" for added and changed functionality, "Fixed" for fixed functionality, and "Removed" for removed functionality is used. -We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#NUM`, -to [sourceforge bugs](https://sourceforge.net/p/jabref/bugs/) by using `bug NUM`, and -to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by using `feature request NUM`. +We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#NUM`. ## [Unreleased] From cb4af8d24e7e3d9db6932b3a956ef2393c033a08 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Thu, 12 May 2016 18:11:42 +0200 Subject: [PATCH 060/268] Add overload for stringy urls in URLDownload (#1375) * Add overload for stringy urls in URLDownload --- .../importer/fetcher/ACMPortalFetcher.java | 8 ++---- .../importer/fetcher/CiteSeerXFetcher.java | 8 ++---- .../jabref/importer/fetcher/DBLPFetcher.java | 11 +++----- .../fetcher/GoogleScholarFetcher.java | 13 ++++------ .../importer/fetcher/IEEEXploreFetcher.java | 8 ++---- .../fetcher/ScienceDirectFetcher.java | 4 +-- .../net/sf/jabref/logic/fulltext/IEEE.java | 2 +- .../net/sf/jabref/logic/net/URLDownload.java | 26 ++++++++++++------- 8 files changed, 33 insertions(+), 47 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java index 4cb7b37fa4a5..f4851c052709 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java @@ -141,9 +141,7 @@ public boolean processQueryGetPreview(String query, FetcherPreviewDialog preview LinkedHashMap previews = new LinkedHashMap<>(); try { - URL url = new URL(address); - - URLDownload dl = new URLDownload(url); + URLDownload dl = new URLDownload(address); String page = dl.downloadToString(); @@ -352,9 +350,7 @@ private static Optional downloadEntryBibTeX(String id, boolean downloa // get abstract if (downloadAbstract) { - url = new URL(ACMPortalFetcher.START_URL + ACMPortalFetcher.ABSTRACT_URL + id); - URLDownload dl = new URLDownload(url); - + URLDownload dl = new URLDownload(ACMPortalFetcher.START_URL + ACMPortalFetcher.ABSTRACT_URL + id); String page = dl.downloadToString(); Matcher absM = ACMPortalFetcher.ABSTRACT_PATTERN.matcher(page); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java index 26d4d1ec2a90..e27f32e7336d 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java @@ -16,7 +16,6 @@ package net.sf.jabref.importer.fetcher; import java.io.IOException; -import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -128,8 +127,7 @@ private List getCitations(String query) throws IOException { } private static String getCitationsFromUrl(String urlQuery, List ids) throws IOException { - URL url = new URL(urlQuery); - String cont = new URLDownload(url).downloadToString(); + String cont = new URLDownload(urlQuery).downloadToString(); Matcher m = CiteSeerXFetcher.CITE_LINK_PATTERN.matcher(cont); while (m.find()) { ids.add(CiteSeerXFetcher.URL_START + m.group(1)); @@ -141,9 +139,7 @@ private static String getCitationsFromUrl(String urlQuery, List ids) thr private static BibEntry getSingleCitation(String urlString) throws IOException { - - URL url = new URL(urlString); - String cont = new URLDownload(url).downloadToString(StandardCharsets.UTF_8); + String cont = new URLDownload(urlString).downloadToString(StandardCharsets.UTF_8); // Find title, and create entry if we do. Otherwise assume we didn't get an entry: Matcher m = CiteSeerXFetcher.TITLE_PATTERN.matcher(cont); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java index 58c955f91b33..b1853e6c85be 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java @@ -17,7 +17,6 @@ package net.sf.jabref.importer.fetcher; import java.io.IOException; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -73,8 +72,7 @@ public boolean processQuery(String newQuery, ImportInspector inspector, try { String address = makeSearchURL(); - URL url = new URL(address); - URLDownload dl = new URLDownload(url); + URLDownload dl = new URLDownload(address); String page = dl.downloadToString(); @@ -102,9 +100,7 @@ public boolean processQuery(String newQuery, ImportInspector inspector, break; } - final URL bibUrl = new URL(urlStr); - - final String bibtexHTMLPage = new URLDownload(bibUrl).downloadToString(); + final String bibtexHTMLPage = new URLDownload(urlStr).downloadToString(); final String[] htmlLines = bibtexHTMLPage.split("\n"); @@ -118,8 +114,7 @@ public boolean processQuery(String newQuery, ImportInspector inspector, // we do not access dblp.uni-trier.de as they will complain bibtexUrl = bibtexUrl.replace("dblp.uni-trier.de", "www.dblp.org"); - final URL bibFileURL = new URL(bibtexUrl); - final String bibtexPage = new URLDownload(bibFileURL).downloadToString(); + final String bibtexPage = new URLDownload(bibtexUrl).downloadToString(); Collection bibtexEntries = BibtexParser.fromString(bibtexPage); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java index 20b66866978e..20779a5618cf 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java @@ -19,7 +19,6 @@ import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; -import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Collection; @@ -174,9 +173,9 @@ public void stopFetching() { private static void runConfig() throws IOException { try { - new URLDownload(new URL("http://scholar.google.com")).downloadToString(); + new URLDownload("http://scholar.google.com").downloadToString(); //save("setting.html", ud.getStringContent()); - String settingsPage = new URLDownload(new URL(GoogleScholarFetcher.URL_SETTING)).downloadToString(); + String settingsPage = new URLDownload(GoogleScholarFetcher.URL_SETTING).downloadToString(); // Get the form items and their values from the page: Map formItems = GoogleScholarFetcher.getFormElements(settingsPage); // Override the important ones: @@ -186,7 +185,7 @@ private static void runConfig() throws IOException { String request = formItems.entrySet().stream().map(Object::toString) .collect(Collectors.joining("&", GoogleScholarFetcher.URL_SETPREFS + "?", "&submit=")); // Download the URL to set preferences: - new URLDownload(new URL(request)).downloadToString(); + new URLDownload(request).downloadToString(); } catch (UnsupportedEncodingException ex) { LOGGER.error("Unsupported encoding.", ex); @@ -217,8 +216,7 @@ private Map getCitations(String query) throws IOException { } private String getCitationsFromUrl(String urlQuery, Map ids) throws IOException { - URL url = new URL(urlQuery); - String cont = new URLDownload(url).downloadToString(); + String cont = new URLDownload(urlQuery).downloadToString(); Matcher m = GoogleScholarFetcher.BIBTEX_LINK_PATTERN.matcher(cont); int lastRegionStart = 0; @@ -265,8 +263,7 @@ private String getCitationsFromUrl(String urlQuery, Map ids) thr private BibEntry downloadEntry(String link) throws IOException { try { - URL url = new URL(GoogleScholarFetcher.URL_START + link); - String s = new URLDownload(url).downloadToString(); + String s = new URLDownload(GoogleScholarFetcher.URL_START + link).downloadToString(); BibtexParser bp = new BibtexParser(new StringReader(s)); ParserResult pr = bp.parse(); if ((pr != null) && (pr.getDatabase() != null)) { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index a8d6c8104e20..ca847f1250dd 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -21,7 +21,6 @@ import java.net.CookieHandler; import java.net.CookieManager; import java.net.MalformedURLException; -import java.net.URL; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -117,9 +116,7 @@ public boolean processQuery(String query, ImportInspector dialog, OutputPrinter try { //open the search URL - URL url = new URL(IEEEXploreFetcher.URL_SEARCH); - - URLDownload dl = new URLDownload(url); + URLDownload dl = new URLDownload(IEEEXploreFetcher.URL_SEARCH); //add request header dl.addParameters("Accept", "application/json"); @@ -159,8 +156,7 @@ public boolean processQuery(String query, ImportInspector dialog, OutputPrinter } //fetch the raw Bibtex results from IEEEXplore - URL bibtexURL = new URL(createBibtexQueryURL(searchResultsJson)); - String bibtexPage = new URLDownload(bibtexURL).downloadToString(); + String bibtexPage = new URLDownload(createBibtexQueryURL(searchResultsJson)).downloadToString(); //preprocess the result (eg. convert HTML escaped characters to latex and do other formatting not performed by BibtexParser) bibtexPage = preprocessBibtexResultsPage(bibtexPage); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java index 7ba5ca2d18a8..9dfdd98fda29 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java @@ -16,7 +16,6 @@ package net.sf.jabref.importer.fetcher; import java.io.IOException; -import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -136,8 +135,7 @@ private static List getCitations(String query) throws IOException { } private static String getCitationsFromUrl(String urlQuery, List ids) throws IOException { - URL url = new URL(urlQuery); - String cont = new URLDownload(url).downloadToString(); + String cont = new URLDownload(urlQuery).downloadToString(); Matcher m = ScienceDirectFetcher.LINK_PATTERN.matcher(cont); if (m.find()) { while (m.find()) { diff --git a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java b/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java index cff5b1444437..28d542aab55c 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java @@ -67,7 +67,7 @@ public Optional findFullText(BibEntry entry) throws IOException { } // Download the HTML page containing a frame with the PDF - String framePage = new URLDownload(new URL(BASE_URL + stampString)).downloadToString(StandardCharsets.UTF_8); + String framePage = new URLDownload(BASE_URL + stampString).downloadToString(StandardCharsets.UTF_8); // Try to find the direct PDF link Matcher matcher = PDF_PATTERN.matcher(framePage); if (matcher.find()) { diff --git a/src/main/java/net/sf/jabref/logic/net/URLDownload.java b/src/main/java/net/sf/jabref/logic/net/URLDownload.java index b0d3c4f252eb..c6fbb6bc2b62 100644 --- a/src/main/java/net/sf/jabref/logic/net/URLDownload.java +++ b/src/main/java/net/sf/jabref/logic/net/URLDownload.java @@ -29,6 +29,7 @@ import java.io.StringWriter; import java.io.Writer; import java.net.CookieHandler; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; @@ -41,6 +42,14 @@ import org.apache.commons.logging.LogFactory; /** + * URL download to a string. + *

    + * Example: + * URLDownload dl = new URLDownload(URL); + * String content = dl.downloadToString(ENCODING); + * dl.downloadToFile(FILE); // available in FILE + * String contentType = dl.determineMimeType(); + * * Each call to a public method creates a new HTTP connection. Nothing is cached. * * @author Erik Putrycz erik.putrycz-at-nrc-cnrc.gc.ca @@ -57,17 +66,16 @@ public class URLDownload { private String postData = ""; /** - * URL download to a string. - *

    - * Example - * URLDownload dl = new URLDownload(URL); - * String content = dl.downloadToString(ENCODING); - * dl.downloadToFile(FILE); // available in FILE - * String contentType = dl.determineMimeType(); - * - * @param source The URL to download. + * @param address the URL to download from + * @throws MalformedURLException if no protocol is specified in the address, or an unknown protocol is found */ + public URLDownload(String address) throws MalformedURLException { + this(new URL(address)); + } + /** + * @param source The URL to download. + */ public URLDownload(URL source) { this.source = source; From b67085e5bbfdb108ff19fd063fef99609a58a444 Mon Sep 17 00:00:00 2001 From: MLEP Date: Thu, 12 May 2016 23:16:55 +0200 Subject: [PATCH 061/268] French localization: translation of empty strings; correction of a glitch (#1393) --- src/main/resources/l10n/JabRef_fr.properties | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 30fdd6d49e70..fac4f5e2e3e8 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1338,7 +1338,7 @@ Old_entry=Ancienne_entrée OpenDocument_presentation=Présentation_OpenDocument OpenDocument_spreadsheet=Tableau_OpenDocument OpenDocument_text=Texte_OpenDocument -Please_move_the_file_manually_and_link_in_place.=Déplacer_le_fichier manuellement_et_lier_le,_SVP. +Please_move_the_file_manually_and_link_in_place.=Déplacez_le_fichier_manuellement_et_liez-le,_SVP. Print_entry_preview=Imprimer_la_prévisualisation_de_l'entrée Really_delete_the_selected_%0_entries?=Voulez-vous_vraiment_supprimer_les_%0_entrées_sélectionnées_? Really_delete_the_selected_entry?=Voulez-vous_vraiment_supprimer_l'entrée_sélectionnée_? @@ -1618,15 +1618,15 @@ All_external_files=Tous_les_fichiers_externes OpenOffice/LibreOffice_integration=Intégration_OpenOffice/LibreOffice -incorrect_control_digit= -incorrect_format= +incorrect_control_digit=chiffre_de_contrôle_incorrect +incorrect_format=format_incorrect -Expected_"%0"_to_contain_whitespace= -Syntax_error_in_regular-expression_pattern= +Expected_"%0"_to_contain_whitespace="%0"_devrait_contenir_une_espace +Syntax_error_in_regular-expression_pattern=Erreur_de_syntaxe_dans_le_format_d'une_expression_régulière -Copy_version_to_clipboard= -Copied_version_to_clipboard= -booktitle_ends_with_'conference_on'= +Copy_version_to_clipboard=Copier_la_version_dans_le_presse-papier +Copied_version_to_clipboard=Version_copiée_dans_le_presse-papier +booktitle_ends_with_'conference_on'=le_titre_d'ouvrage_se_termine_par_'conference_on' -BibTeX_key= -Message= \ No newline at end of file +BibTeX_key=Clef_BibTeX +Message=Message From c6eed0e54b5949f7a9c68b779432e0dc8892bb49 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Fri, 13 May 2016 12:37:08 +0200 Subject: [PATCH 062/268] Fixed sourceforge bug 1000: shorttitleINI can generate the initials of the shorttitle --- CHANGELOG.md | 1 + .../logic/labelpattern/LabelPatternUtil.java | 14 ++++++++++---- .../logic/labelpattern/LabelPatternUtilTest.java | 8 ++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a57ce7ae5c6f..031609537ef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#796](https://github.com/JabRef/jabref/issues/796): Undoing more than one entry at the same time is now working - Fixed [#1353](https://github.com/JabRef/jabref/issues/1353): Fetch-Preview did not display updated BibTeX-Key after clicking on `Generate Now` - Fixed [#1381](https://github.com/JabRef/jabref/issues/1381): File links containing blanks are broken if non-default viewer is set +- Fixed sourceforge bug 1000: shorttitleINI can generate the initials of the shorttitle ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index 1ca740b8a408..14659ad66ac7 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -564,9 +564,9 @@ public static String applyModifiers(String label, String[] parts, int offset) { StringBuilder abbreviateSB = new StringBuilder(); String[] words = resultingLabel.replaceAll("[\\{\\}']", "") .split("[\\(\\) \r\n\"]"); - for (String word1 : words) { - if (!word1.isEmpty()) { - abbreviateSB.append(word1.charAt(0)); + for (String word : words) { + if (!word.isEmpty()) { + abbreviateSB.append(word.charAt(0)); } } resultingLabel = abbreviateSB.toString(); @@ -740,6 +740,8 @@ else if (val.matches("edtr\\d+")) { return lastPage(entry.getField("pages")); } else if ("shorttitle".equals(val)) { return getTitleWords(3, entry.getField("title")); + } else if ("shorttitleINI".equals(val)) { + return keepLettersAndDigitsOnly(applyModifiers(getTitleWordsWithSpaces(3, entry.getField("title")), new String[] {"abbr"}, 0)); } else if ("veryshorttitle".equals(val)) { return getTitleWords(1, entry.getField("title")); } else if ("shortyear".equals(val)) { @@ -825,6 +827,10 @@ private static String getAddition(int number) { * Determines "number" words out of the "title" field in the given BibTeX entry */ public static String getTitleWords(int number, String title) { + return keepLettersAndDigitsOnly(getTitleWordsWithSpaces(number, title)); + } + + private static String getTitleWordsWithSpaces(int number, String title) { String ss = new RemoveLatexCommands().format(title); StringBuilder stringBuilder = new StringBuilder(); StringBuilder current; @@ -861,7 +867,7 @@ public static String getTitleWords(int number, String title) { words++; } - return keepLettersAndDigitsOnly(stringBuilder.toString()); + return stringBuilder.toString(); } private static String keepLettersAndDigitsOnly(String in) { diff --git a/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java b/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java index 165554a43f59..8c658a94ae78 100644 --- a/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java @@ -723,4 +723,12 @@ public void testCheckLegalKey2() { assertEquals("", LabelPatternUtil.checkLegalKey("\n\t\r")); } + @Test + public void testApplyModifiers() { + BibEntry entry = new BibEntry(); + entry.setField("title", "Green Scheduling of Whatever"); + assertEquals("GSW", LabelPatternUtil.makeLabel(entry, "shorttitleINI")); + assertEquals("GreenSchedulingWhatever", LabelPatternUtil.makeLabel(entry, "shorttitle")); + } + } From 63368db7a6d9cd4e1bade4bdff49d9d631655d1a Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Fri, 13 May 2016 18:14:08 +0200 Subject: [PATCH 063/268] Fix personal journal list saving #1394 File was not created before writing to it. Use nio methods --- CHANGELOG.md | 3 +- .../gui/journals/ManageJournalsPanel.java | 76 +++++++++---------- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 031609537ef6..6a86be78f424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,11 +43,12 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1340](https://github.com/JabRef/jabref/issues/1340): Edit -> Mark Specific Color Dysfunctional on OSX - Fixed [#1245](https://github.com/JabRef/jabref/issues/1245): Empty jstyle properties can now be specified as "" - Fixed [#1364](https://github.com/JabRef/jabref/issues/1364): Windows: install to LOCALAPPDATA directory for non-admin users -- Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to "[auth][year]" +- Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to `[auth][year]` - Fixed [#796](https://github.com/JabRef/jabref/issues/796): Undoing more than one entry at the same time is now working - Fixed [#1353](https://github.com/JabRef/jabref/issues/1353): Fetch-Preview did not display updated BibTeX-Key after clicking on `Generate Now` - Fixed [#1381](https://github.com/JabRef/jabref/issues/1381): File links containing blanks are broken if non-default viewer is set - Fixed sourceforge bug 1000: shorttitleINI can generate the initials of the shorttitle +- Fixed [#1394](https://github.com/JabRef/jabref/issues/1394): Personal journal abbrevations could not be saved ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java index 5c269ba95e59..aed710d96d76 100644 --- a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java +++ b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -24,10 +24,14 @@ import java.awt.event.MouseListener; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -189,11 +193,11 @@ public ManageJournalsPanel(final JabRefFrame frame) { }); browseNew.addActionListener(e -> { - File old = null; - if (!"".equals(newNameTf.getText())) { - old = new File(newNameTf.getText()); + Path old = null; + if (!newNameTf.getText().isEmpty()) { + old = Paths.get(newNameTf.getText()); } - String name = FileDialogs.getNewFile(frame, old, null, JFileChooser.SAVE_DIALOG, false); + String name = FileDialogs.getNewFile(frame, old.toFile(), null, JFileChooser.SAVE_DIALOG, false); if (name != null) { newNameTf.setText(name); newFile.setSelected(true); @@ -201,11 +205,11 @@ public ManageJournalsPanel(final JabRefFrame frame) { }); browseOld.addActionListener(e -> { - File old = null; - if (!"".equals(personalFile.getText())) { - old = new File(personalFile.getText()); + Path old = null; + if (!personalFile.getText().isEmpty()) { + old = Paths.get(personalFile.getText()); } - String name = FileDialogs.getNewFile(frame, old, null, JFileChooser.OPEN_DIALOG, false); + String name = FileDialogs.getNewFile(frame, old.toFile(), null, JFileChooser.OPEN_DIALOG, false); if (name != null) { personalFile.setText(name); oldFile.setSelected(true); @@ -216,15 +220,8 @@ public ManageJournalsPanel(final JabRefFrame frame) { ok.addActionListener(e -> { if (readyToClose()) { - try { - storeSettings(); - dialog.dispose(); - } catch (FileNotFoundException ex) { - JOptionPane.showMessageDialog(null, - Localization.lang("Error opening file") + ": " + ex.getMessage(), - Localization.lang("Error opening file"), JOptionPane.ERROR_MESSAGE); - LOGGER.debug("Cannot find abbreviation file", ex); - } + storeSettings(); + dialog.dispose(); } }); @@ -291,8 +288,6 @@ private void buildExternalsPanel() { builder.add(addExtPan).xy(1, row + 2); builder.add(Box.createVerticalGlue()).xy(1, row + 2); - //builder.getPanel().setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.green)); - //externalFilesPanel.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.red)); JScrollPane pane = new JScrollPane(builder.getPanel()); pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); externalFilesPanel.setMinimumSize(new Dimension(400, 400)); @@ -320,7 +315,7 @@ private void setupExternals() { private void setupUserTable() { List userAbbreviations = new ArrayList<>(); String filename = personalFile.getText(); - if ((!filename.isEmpty()) && new File(filename).exists()) { + if (!filename.isEmpty() && Files.exists(Paths.get(filename))) { try { userAbbreviations = JournalAbbreviationLoader.readJournalListFromFile(new File(filename), Globals.prefs.getDefaultEncoding()); @@ -336,7 +331,7 @@ private void setupUserTable() { } private boolean readyToClose() { - File f; + Path filePath; if (newFile.isSelected()) { if (newNameTf.getText().isEmpty()) { if (tableModel.getRowCount() > 0) { @@ -348,9 +343,9 @@ private boolean readyToClose() { return true; } } else { - f = new File(newNameTf.getText()); - return !f.exists() || (JOptionPane.showConfirmDialog(this, - Localization.lang("'%0' exists. Overwrite file?", f.getName()), + filePath = Paths.get(newNameTf.getText()); + return !Files.exists(filePath) || (JOptionPane.showConfirmDialog(this, + Localization.lang("'%0' exists. Overwrite file?", filePath.getFileName().toString()), Localization.lang("Store journal abbreviations"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION); } @@ -358,21 +353,19 @@ private boolean readyToClose() { return true; } - private void storeSettings() throws FileNotFoundException { - File f = null; + private void storeSettings() { + Path filePath = null; if (newFile.isSelected()) { if (!newNameTf.getText().isEmpty()) { - f = new File(newNameTf.getText()); + filePath = Paths.get(newNameTf.getText()); } } else { - f = new File(personalFile.getText()); + filePath = Paths.get(personalFile.getText()); + } - if (f != null) { - if (!f.exists()) { - throw new FileNotFoundException(f.getAbsolutePath()); - } - try (FileOutputStream stream = new FileOutputStream(f, false); + if (filePath != null) { + try (OutputStream stream = Files.newOutputStream(filePath, StandardOpenOption.CREATE); OutputStreamWriter writer = new OutputStreamWriter(stream, Globals.prefs.getDefaultEncoding())) { for (JournalEntry entry : tableModel.getJournals()) { writer.write(entry.getName()); @@ -383,7 +376,7 @@ private void storeSettings() throws FileNotFoundException { } catch (IOException e) { LOGGER.warn("Problem writing abbreviation file", e); } - String filename = f.getPath(); + String filename = filePath.toString(); if ("".equals(filename)) { filename = null; } @@ -461,15 +454,12 @@ public BrowseAction(JTextField tc, boolean dir) { public void actionPerformed(ActionEvent e) { String chosen; if (dir) { - chosen = FileDialogs.getNewDir(frame, new File(comp.getText()), "", JFileChooser.OPEN_DIALOG, - false); + chosen = FileDialogs.getNewDir(frame, new File(comp.getText()), "", JFileChooser.OPEN_DIALOG, false); } else { - chosen = FileDialogs.getNewFile(frame, new File(comp.getText()), "", JFileChooser.OPEN_DIALOG, - false); + chosen = FileDialogs.getNewFile(frame, new File(comp.getText()), "", JFileChooser.OPEN_DIALOG, false); } if (chosen != null) { - File nFile = new File(chosen); - comp.setText(nFile.getPath()); + comp.setText(Paths.get(chosen).toString()); } } } @@ -480,6 +470,7 @@ class AbbreviationsTableModel extends AbstractTableModel implements ActionListen Localization.lang("Abbreviation")}; private List journals; + public void setJournals(List abbreviations) { this.journals = new ArrayList<>(); for (Abbreviation abbreviation : abbreviations) { @@ -676,6 +667,7 @@ public boolean equals(Object o) { public int hashCode() { return this.name.hashCode(); } + public String getName() { return name; } From 776895e8317332bb4e22f92f6a1d0e3c96ffdb1f Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sat, 14 May 2016 12:26:37 +0200 Subject: [PATCH 064/268] Fix #1400 Detect path constructs wrong path for Windows --- src/main/java/net/sf/jabref/gui/desktop/os/Windows.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java b/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java index 3fe266e56f05..a43023c548e0 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java +++ b/src/main/java/net/sf/jabref/gui/desktop/os/Windows.java @@ -34,9 +34,9 @@ public String detectProgramPath(String programName, String directoryName) { progFiles = System.getenv("ProgramFiles"); } if ((directoryName != null) && !directoryName.isEmpty()) { - return Paths.get(progFiles, directoryName, programName, DEFAULT_EXECUTABLE_EXTENSION).toString(); + return Paths.get(progFiles, directoryName, programName + DEFAULT_EXECUTABLE_EXTENSION).toString(); } - return Paths.get(progFiles, programName, DEFAULT_EXECUTABLE_EXTENSION).toString(); + return Paths.get(progFiles, programName + DEFAULT_EXECUTABLE_EXTENSION).toString(); } @Override From cf7f68676c228a46eab219b28ee757d8416dd64f Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 15 May 2016 12:03:11 +0200 Subject: [PATCH 065/268] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a86be78f424..732a33fa0287 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1381](https://github.com/JabRef/jabref/issues/1381): File links containing blanks are broken if non-default viewer is set - Fixed sourceforge bug 1000: shorttitleINI can generate the initials of the shorttitle - Fixed [#1394](https://github.com/JabRef/jabref/issues/1394): Personal journal abbrevations could not be saved +- Fixed [#1400](https://github.com/JabRef/jabref/issues/1400): Detect path constructs wrong path for Windows ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic From 86bf5d16c5d65f33c30a661d9e512899a51cda7d Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Mon, 16 May 2016 18:39:06 +0200 Subject: [PATCH 066/268] Fix #993 Saving an invalid BibTeX source --- .../sf/jabref/gui/entryeditor/EntryEditor.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index d2b76a86cceb..80f62ecca5d1 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -177,6 +177,7 @@ public class EntryEditor extends JPanel implements EntryContainer { private boolean updateSource = true; // This can be set to false to stop the source private boolean movingToDifferentEntry; // Indicates that we are about to go to the next or previous entry + private boolean validEntry = true; private final List tabs = new ArrayList<>(); @@ -1213,7 +1214,7 @@ public void actionPerformed(ActionEvent event) { } } else if (source.isEditable() && !source.getText().equals(lastSourceStringAccepted)) { - storeSource(); + validEntry = storeSource(); } // Make sure we scroll to the entry if it moved in the table. @@ -1404,18 +1405,18 @@ public void actionPerformed(ActionEvent e) { Object activeTab = tabs.get(tabbed.getSelectedIndex()); if (activeTab instanceof EntryEditorTab) { // Normal panel. - EntryEditorTab fp = (EntryEditorTab) activeTab; - FieldEditor fe = fp.getActive(); - fe.clearAutoCompleteSuggestion(); - updateField(fe); + EntryEditorTab tab = (EntryEditorTab) activeTab; + FieldEditor fieldEditor = tab.getActive(); + fieldEditor.clearAutoCompleteSuggestion(); + updateField(fieldEditor); } else { // Source panel. updateField(activeTab); } - - panel.runCommand(Actions.SAVE); - + if (validEntry) { + panel.runCommand(Actions.SAVE); + } } } From 9a9c20611891adbed09b2fea5fc2207bd28a8393 Mon Sep 17 00:00:00 2001 From: Admir Obralija Date: Mon, 16 May 2016 19:06:20 +0200 Subject: [PATCH 067/268] Fix small event bug in PreviewPanel.java --- src/main/java/net/sf/jabref/gui/PreviewPanel.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index bfba1e91cef8..25490721b205 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -275,13 +275,9 @@ public void setLayout(Layout layout) { public void setEntry(BibEntry newEntry) { - if (entry.isPresent() && (entry.get() != newEntry)) { - entry.ifPresent(e -> e.unregisterListener(this)); - } - if(newEntry != null) { - newEntry.registerListener(this); - } + entry.filter(e -> e != newEntry).ifPresent(e -> e.unregisterListener(this)); entry = Optional.ofNullable(newEntry); + entry.ifPresent(e -> e.registerListener(this)); updateLayout(); update(); From 453874377d80d6bcc2ea7121cbf162dca6ef3562 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Mon, 16 May 2016 19:20:05 +0200 Subject: [PATCH 068/268] Fix #1402 Open file dialog in last working directory if file was not found --- .../sf/jabref/gui/FileListEntryEditor.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java index 75cd2786ea80..e238934e40ba 100644 --- a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java @@ -345,11 +345,9 @@ public boolean okPressed() { class BrowseListener implements ActionListener { - private final JFrame parent; private final JTextField comp; - public BrowseListener(JFrame parent, JTextField comp) { this.parent = parent; this.comp = comp; @@ -357,21 +355,25 @@ public BrowseListener(JFrame parent, JTextField comp) { @Override public void actionPerformed(ActionEvent e) { - File initial = new File(comp.getText().trim()); - if (comp.getText().trim().isEmpty()) { - // Nothing in the field. Go to the last file dir used: - initial = new File(Globals.prefs.get(JabRefPreferences.FILE_WORKING_DIRECTORY)); + String filePath = comp.getText().trim(); + Optional file = FileUtil.expandFilename(databaseContext, filePath); + File workingDir; + // no file set yet or found + if (file.isPresent()) { + workingDir = new File(file.get().getParent()); + } else { + workingDir = new File(Globals.prefs.get(JabRefPreferences.FILE_WORKING_DIRECTORY)); } - String chosen = FileDialogs.getNewFile(parent, initial, "", - JFileChooser.OPEN_DIALOG, false); - if (chosen != null) { - File newFile = new File(chosen); + + String selection = FileDialogs.getNewFile(parent, workingDir, "", JFileChooser.OPEN_DIALOG, false); + if (selection != null) { + File newFile = new File(selection); // Store the directory for next time: Globals.prefs.put(JabRefPreferences.FILE_WORKING_DIRECTORY, newFile.getParent()); // If the file is below the file directory, make the path relative: - List dirsS = databaseContext.getFileDirectory(); - newFile = FileUtil.shortenFileName(newFile, dirsS); + List fileDirs = databaseContext.getFileDirectory(); + newFile = FileUtil.shortenFileName(newFile, fileDirs); comp.setText(newFile.getPath()); comp.requestFocus(); From db843c9d6c19e1a6fe6c3f20c326d65ce2ba793b Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Tue, 17 May 2016 19:48:31 +0200 Subject: [PATCH 069/268] Fix #1399 export to html: html code is not well-formed --- .../net/sf/jabref/exporter/ExportFormat.java | 2 +- .../net/sf/jabref/exporter/ExportFormats.java | 9 +-- .../jabref/exporter/HtmlExportFormatTest.java | 64 +++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormat.java b/src/main/java/net/sf/jabref/exporter/ExportFormat.java index 27bcd440bc61..642cc70fc249 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/ExportFormat.java @@ -293,7 +293,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String } // Write footer - if ((endLayout != null) && (this.encoding != null)) { + if (endLayout != null) { ps.write(endLayout.doLayout(databaseContext, this.encoding)); missingFormatters.addAll(endLayout.getMissingFormatters()); } diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormats.java b/src/main/java/net/sf/jabref/exporter/ExportFormats.java index 23229077ccbd..c59762c53454 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFormats.java +++ b/src/main/java/net/sf/jabref/exporter/ExportFormats.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -42,13 +42,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -/** - * User: alver - * - * Date: Oct 18, 2006 - * - * Time: 9:35:08 PM - */ public class ExportFormats { private static final Log LOGGER = LogFactory.getLog(ExportFormats.class); diff --git a/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java b/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java new file mode 100644 index 000000000000..9bdbb2c18c54 --- /dev/null +++ b/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java @@ -0,0 +1,64 @@ +package net.sf.jabref.exporter; + +import java.io.File; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.List; + +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.MetaData; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.entry.BibEntry; + +import com.google.common.base.Charsets; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import static org.junit.Assert.assertEquals; + +public class HtmlExportFormatTest { + private IExportFormat exportFormat; + public BibDatabaseContext databaseContext; + public Charset charset; + public List entries; + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + @Before + public void setUp() { + Globals.prefs = JabRefPreferences.getInstance(); + ExportFormats.initAllExports(); + exportFormat = ExportFormats.getExportFormat("html"); + + Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(Globals.prefs); + databaseContext = new BibDatabaseContext(new BibDatabase(), new MetaData()); + charset = Charsets.UTF_8; + BibEntry entry = new BibEntry(); + entry.setField("title", "my paper title"); + entry.setField("author", "Stefan Kolb"); + entry.setCiteKey("mykey"); + entries = Arrays.asList(entry); + } + + @After + public void tearDown() { + exportFormat = null; + } + + @Test + public void emitWellFormedHtml() throws Exception { + File tmpFile = testFolder.newFile(); + String filename = tmpFile.getCanonicalPath(); + exportFormat.performExport(databaseContext, filename, charset, entries); + List lines = Files.readAllLines(tmpFile.toPath()); + assertEquals("", lines.get(lines.size() - 1)); + } +} From f4270a6a67881c124d86ffe9703ec758758d151a Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 18 May 2016 20:41:54 +0200 Subject: [PATCH 070/268] Remove StringUtil.expandAuthorInitials (#1373) --- CHANGELOG.md | 3 +- .../sf/jabref/importer/fetcher/GVKParser.java | 5 +- .../importer/fileformat/MedlineHandler.java | 3 +- .../jabref/logic/util/strings/StringUtil.java | 48 ---------------- .../logic/util/strings/StringUtilTest.java | 43 +------------- .../net/sf/jabref/model/entry/AuthorTest.java | 56 +++++++++++++++++++ 6 files changed, 61 insertions(+), 97 deletions(-) create mode 100644 src/test/java/net/sf/jabref/model/entry/AuthorTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 732a33fa0287..5ccf27f07090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,8 +55,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic - Removed support of old groups format, which was used prior to JabRef version 1.6. If you happen to have a 10 years old .bib file, then JabRef 3.3 can be used to convert it to the current format. - Removed possibility to automatically add braces via Option - Preferences - File - Store the following fields with braces around capital letters. Please use save actions instead for adding braces automatically. - - +- Medline and GVK importer no longer try to expand author initials (i.e. `EH Wissler -> E. H. Wissler`). diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java index 786bc447324c..07eb33eb27b7 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -12,7 +12,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; @@ -365,10 +364,10 @@ private BibEntry parseEntry(Element e) { // Zuordnung der Felder in Abhängigkeit vom Dokumenttyp if (author != null) { - result.setField("author", StringUtil.expandAuthorInitials(author)); + result.setField("author", author); } if (editor != null) { - result.setField("editor", StringUtil.expandAuthorInitials(editor)); + result.setField("editor", editor); } if (title != null) { result.setField("title", title); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java index 006f5c121070..5b7a9f8a6430 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java @@ -22,7 +22,6 @@ import java.util.TreeSet; import net.sf.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter; -import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; @@ -229,7 +228,7 @@ public void endElement(String uri, String localName, String qName) { BibEntry b = new BibEntry(IdGenerator.next(), "article"); // id assumes an existing database so don't create one here if (!"".equals(author)) { b.setField("author", - MedlineHandler.UNICODE_CONVERTER.format(StringUtil.expandAuthorInitials(author))); + MedlineHandler.UNICODE_CONVERTER.format(author)); // b.setField("author",Util.replaceSpecialCharacters(ImportFormatReader.expandAuthorInitials(author))); author = ""; } diff --git a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java index 5db1e62071f8..86a6e3bdf6cb 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java @@ -23,7 +23,6 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.model.entry.Author; import com.google.common.base.CharMatcher; @@ -626,53 +625,6 @@ public static String replaceSpecialCharacters(String s) { return result; } - /** - * Expand initials, e.g. EH Wissler -> E. H. Wissler or Wissler, EH -> Wissler, E. H. - * - * @param name - * @return The name after expanding initials. - */ - public static String expandAuthorInitials(String name) { - String[] authors = name.split(" and "); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < authors.length; i++) { - if (authors[i].contains(", ")) { - String[] names = authors[i].split(", "); - if (names.length > 0) { - sb.append(names[0]); - if (names.length > 1) { - sb.append(", "); - } - } - for (int j = 1; j < names.length; j++) { - if (j == 1) { - sb.append(Author.addDotIfAbbreviation(names[j])); - } else { - sb.append(names[j]); - } - if (j < (names.length - 1)) { - sb.append(", "); - } - } - - } else { - String[] names = authors[i].split(" "); - if (names.length > 0) { - sb.append(Author.addDotIfAbbreviation(names[0])); - } - for (int j = 1; j < names.length; j++) { - sb.append(' '); - sb.append(names[j]); - } - } - if (i < (authors.length - 1)) { - sb.append(" and "); - } - } - - return sb.toString().trim(); - } - /** * Return a String with n spaces * diff --git a/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java b/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java index 83a208f9cad5..8a8557edff52 100644 --- a/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java @@ -289,47 +289,6 @@ public void testReplaceSpecialCharacters() { assertEquals("aaAeoeeee", StringUtil.replaceSpecialCharacters("åÄöéèë")); } - @Test - public void testExpandAuthorInitialsAddDot() { - assertEquals("O.", StringUtil.expandAuthorInitials("O")); - assertEquals("A. O.", StringUtil.expandAuthorInitials("AO")); - assertEquals("A. O.", StringUtil.expandAuthorInitials("AO.")); - assertEquals("A. O.", StringUtil.expandAuthorInitials("A.O.")); - assertEquals("A.-O.", StringUtil.expandAuthorInitials("A-O")); - assertEquals("O. Moore", StringUtil.expandAuthorInitials("O Moore")); - assertEquals("A. O. Moore", StringUtil.expandAuthorInitials("AO Moore")); - assertEquals("O. von Moore", StringUtil.expandAuthorInitials("O von Moore")); - assertEquals("A.-O. Moore", StringUtil.expandAuthorInitials("A-O Moore")); - assertEquals("Moore, O.", StringUtil.expandAuthorInitials("Moore, O")); - assertEquals("Moore, O., Jr.", StringUtil.expandAuthorInitials("Moore, O, Jr.")); - assertEquals("Moore, A. O.", StringUtil.expandAuthorInitials("Moore, AO")); - assertEquals("Moore, A.-O.", StringUtil.expandAuthorInitials("Moore, A-O")); - assertEquals("Moore, O. and O. Moore", StringUtil.expandAuthorInitials("Moore, O and O Moore")); - assertEquals("Moore, O. and O. Moore and Moore, O. O.", - StringUtil.expandAuthorInitials("Moore, O and O Moore and Moore, OO")); - } - - @Test - public void testExpandAuthorInitialsDoNotAddDot() { - assertEquals("O.", StringUtil.expandAuthorInitials("O.")); - assertEquals("A. O.", StringUtil.expandAuthorInitials("A. O.")); - assertEquals("A.-O.", StringUtil.expandAuthorInitials("A.-O.")); - assertEquals("O. Moore", StringUtil.expandAuthorInitials("O. Moore")); - assertEquals("A. O. Moore", StringUtil.expandAuthorInitials("A. O. Moore")); - assertEquals("O. von Moore", StringUtil.expandAuthorInitials("O. von Moore")); - assertEquals("A.-O. Moore", StringUtil.expandAuthorInitials("A.-O. Moore")); - assertEquals("Moore, O.", StringUtil.expandAuthorInitials("Moore, O.")); - assertEquals("Moore, O., Jr.", StringUtil.expandAuthorInitials("Moore, O., Jr.")); - assertEquals("Moore, A. O.", StringUtil.expandAuthorInitials("Moore, A. O.")); - assertEquals("Moore, A.-O.", StringUtil.expandAuthorInitials("Moore, A.-O.")); - assertEquals("MEmre", StringUtil.expandAuthorInitials("MEmre")); - assertEquals("{\\'{E}}douard", StringUtil.expandAuthorInitials("{\\'{E}}douard")); - assertEquals("J{\\\"o}rg", StringUtil.expandAuthorInitials("J{\\\"o}rg")); - assertEquals("Moore, O. and O. Moore", StringUtil.expandAuthorInitials("Moore, O. and O. Moore")); - assertEquals("Moore, O. and O. Moore and Moore, O. O.", - StringUtil.expandAuthorInitials("Moore, O. and O. Moore and Moore, O. O.")); - } - @Test public void testRepeatSpaces() { assertEquals("", StringUtil.repeatSpaces(0)); @@ -343,4 +302,4 @@ public void testRepeat() { assertEquals("a", StringUtil.repeat(1, 'a')); assertEquals("aaaaaaa", StringUtil.repeat(7, 'a')); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/model/entry/AuthorTest.java b/src/test/java/net/sf/jabref/model/entry/AuthorTest.java new file mode 100644 index 000000000000..8600cecc9bc3 --- /dev/null +++ b/src/test/java/net/sf/jabref/model/entry/AuthorTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2003-2016 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.model.entry; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class AuthorTest { + + @Test + public void addDotIfAbbreviationAddDot() { + assertEquals("O.", Author.addDotIfAbbreviation("O")); + assertEquals("A. O.", Author.addDotIfAbbreviation("AO")); + assertEquals("A. O.", Author.addDotIfAbbreviation("AO.")); + assertEquals("A. O.", Author.addDotIfAbbreviation("A.O.")); + assertEquals("A.-O.", Author.addDotIfAbbreviation("A-O")); + } + + @Test + public void addDotIfAbbreviationDoNotAddDot() { + assertEquals("O.", Author.addDotIfAbbreviation("O.")); + assertEquals("A. O.", Author.addDotIfAbbreviation("A. O.")); + assertEquals("A.-O.", Author.addDotIfAbbreviation("A.-O.")); + assertEquals("O. Moore", Author.addDotIfAbbreviation("O. Moore")); + assertEquals("A. O. Moore", Author.addDotIfAbbreviation("A. O. Moore")); + assertEquals("O. von Moore", Author.addDotIfAbbreviation("O. von Moore")); + assertEquals("A.-O. Moore", Author.addDotIfAbbreviation("A.-O. Moore")); + assertEquals("Moore, O.", Author.addDotIfAbbreviation("Moore, O.")); + assertEquals("Moore, O., Jr.", Author.addDotIfAbbreviation("Moore, O., Jr.")); + assertEquals("Moore, A. O.", Author.addDotIfAbbreviation("Moore, A. O.")); + assertEquals("Moore, A.-O.", Author.addDotIfAbbreviation("Moore, A.-O.")); + assertEquals("MEmre", Author.addDotIfAbbreviation("MEmre")); + assertEquals("{\\'{E}}douard", Author.addDotIfAbbreviation("{\\'{E}}douard")); + assertEquals("J{\\\"o}rg", Author.addDotIfAbbreviation("J{\\\"o}rg")); + assertEquals("Moore, O. and O. Moore", Author.addDotIfAbbreviation("Moore, O. and O. Moore")); + assertEquals("Moore, O. and O. Moore and Moore, O. O.", + Author.addDotIfAbbreviation("Moore, O. and O. Moore and Moore, O. O.")); + } + +} From e13d7f10b23e3b03c9f6425704ad46a973c90023 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 18 May 2016 20:55:25 +0200 Subject: [PATCH 071/268] Fix 1334: Display correct number of entries in static groups (#1384) --- .../gui/groups/GroupTreeNodeViewModel.java | 22 ++---- .../sf/jabref/logic/groups/AbstractGroup.java | 15 ++++ .../sf/jabref/logic/groups/ExplicitGroup.java | 4 -- .../net/sf/jabref/model/entry/BibEntry.java | 4 ++ .../logic/groups/AbstractGroupTest.java | 68 +++++++++++++++++++ 5 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java index c8bf0aec47e7..cfc8b148c743 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -41,11 +41,8 @@ import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.AllEntriesGroup; import net.sf.jabref.logic.groups.EntriesGroupChange; -import net.sf.jabref.logic.groups.ExplicitGroup; import net.sf.jabref.logic.groups.GroupTreeNode; -import net.sf.jabref.logic.groups.KeywordGroup; import net.sf.jabref.logic.groups.MoveGroupChange; -import net.sf.jabref.logic.groups.SearchGroup; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; @@ -196,20 +193,11 @@ public String getText() { StringBuilder sb = new StringBuilder(60); sb.append(name); - if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS)) { - if (group instanceof ExplicitGroup) { - sb.append(" [").append(((ExplicitGroup) group).getNumEntries()).append(']'); - } else if ((group instanceof KeywordGroup) || (group instanceof SearchGroup)) { - int hits = 0; - BasePanel currentBasePanel = JabRefGUI.getMainFrame().getCurrentBasePanel(); - if(currentBasePanel != null) { - for (BibEntry entry : currentBasePanel.getDatabase().getEntries()) { - if (group.contains(entry)) { - hits++; - } - } - } - sb.append(" [").append(hits).append(']'); + if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS) + && JabRefGUI.getMainFrame() != null) { + BasePanel currentBasePanel = JabRefGUI.getMainFrame().getCurrentBasePanel(); + if (currentBasePanel != null) { + sb.append(" [").append(group.numberOfHits(currentBasePanel.getDatabase().getEntries())).append(']'); } } diff --git a/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java b/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java index 10f1ea3c35d3..26026deda4d8 100644 --- a/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java @@ -168,6 +168,21 @@ public boolean containsAll(List entries) { return true; } + /** + * Determines the number of entries in the specified list which are matched by this group. + * @param entries list of entries to be searched + * @return number of hits + */ + public int numberOfHits(List entries) { + int hits = 0; + for (BibEntry entry : entries) { + if (this.contains(entry)) { + hits++; + } + } + return hits; + } + /** * Returns true if this group is dynamic, i.e. uses a search definition or * equiv. that might match new entries, or false if this group contains a diff --git a/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java b/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java index c73f8a7784ab..83802db7eec7 100644 --- a/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java @@ -168,10 +168,6 @@ public String getTypeId() { return ExplicitGroup.ID; } - public int getNumEntries() { - return legacyEntryKeys.size(); - } - @Override public int hashCode() { return super.hashCode(); diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 9818269164fa..7a14564f8120 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -611,4 +611,8 @@ public void unregisterListener(Object object) { this.eventBus.unregister(object); } + public BibEntry withField(String field, String value) { + setField(field, value); + return this; + } } diff --git a/src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java new file mode 100644 index 000000000000..8fd8329c6b8f --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2003-2016 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.groups; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.sf.jabref.model.entry.BibEntry; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AbstractGroupTest { + + private AbstractGroup group; + private List entries = new ArrayList<>(); + + @Before + public void setUp() throws Exception { + group = mock(AbstractGroup.class, Mockito.CALLS_REAL_METHODS); + + entries.add(new BibEntry().withField("author", "author1 and author2")); + entries.add(new BibEntry().withField("author", "author1")); + } + + @Test + public void numberOfHitsReturnsZeroForEmptyList() throws Exception { + assertEquals(0, group.numberOfHits(Collections.emptyList())); + } + + @Test + public void numberOfHitsCallsContainsToDetermineSingleHit() throws Exception { + when(group.contains(any())).then(invocation -> + invocation.getArgumentAt(0, BibEntry.class).getField("author").contains("author2")); + assertEquals(1, group.numberOfHits(entries)); + } + + @Test + public void numberOfHitsCallsContainsToDetermineMultipleHits() throws Exception { + when(group.contains(any())).then(invocation -> + invocation.getArgumentAt(0, BibEntry.class).getField("author").contains("author1")); + assertEquals(2, group.numberOfHits(entries)); + } + + +} From 4ee388a1318ce6e42abf1faa0baa46864611c41c Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 11 May 2016 20:56:58 +0200 Subject: [PATCH 072/268] Remove group refresh button and some small restyleing --- CHANGELOG.md | 2 + .../sf/jabref/gui/groups/GroupSelector.java | 112 ++++++------------ 2 files changed, 38 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ccf27f07090..54942ac60c2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic - Removed support of old groups format, which was used prior to JabRef version 1.6. If you happen to have a 10 years old .bib file, then JabRef 3.3 can be used to convert it to the current format. - Removed possibility to automatically add braces via Option - Preferences - File - Store the following fields with braces around capital letters. Please use save actions instead for adding braces automatically. +- Removed button to refresh groups view. This button shouldn't be needed anymore. Please report any cases where the groups view is not updated automatically. - Medline and GVK importer no longer try to expand author initials (i.e. `EH Wissler -> E. H. Wissler`). @@ -70,6 +71,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# + ## [3.3] - 2016-04-17 ### Changed diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 16325c4d79e1..284c36e085f4 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -23,7 +23,6 @@ import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -45,7 +44,6 @@ import javax.swing.JRadioButtonMenuItem; import javax.swing.JScrollPane; import javax.swing.KeyStroke; -import javax.swing.border.Border; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -92,10 +90,6 @@ public class GroupSelector extends SidePaneComponent implements TreeSelectionLis private static final Log LOGGER = LogFactory.getLog(GroupSelector.class); - private final JButton newButton = new JButton(IconTheme.JabRefIcon.ADD_NOBOX.getSmallIcon()); - private final JButton refresh = new JButton(IconTheme.JabRefIcon.REFRESH.getSmallIcon()); - private final JButton autoGroup = new JButton(IconTheme.JabRefIcon.AUTO_GROUP.getSmallIcon()); - private final JButton openset = new JButton(Localization.lang("Settings")); private final GroupsTree groupsTree; private DefaultTreeModel groupsTreeModel; private GroupTreeNodeViewModel groupsRoot; @@ -116,9 +110,6 @@ public class GroupSelector extends SidePaneComponent implements TreeSelectionLis Localization.lang("Automatically assign new entry to selected groups")); private final JCheckBoxMenuItem editModeCb = new JCheckBoxMenuItem(Localization.lang("Edit group membership"), false); - private final Border editModeBorder = BorderFactory.createTitledBorder( - BorderFactory.createMatteBorder(2, 2, 2, 2, Color.RED), "Edit mode", TitledBorder.RIGHT, TitledBorder.TOP, - Font.getFont("Default"), Color.RED); private boolean editModeIndicator; private static final String MOVE_ONE_GROUP = Localization.lang("Please select exactly one group to move."); @@ -219,7 +210,7 @@ public void stateChanged(ChangeEvent e) { showNumberOfElements.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS)); autoAssignGroup.setSelected(Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); - openset.setMargin(new Insets(0, 0, 0, 0)); + JButton openSettings = new JButton(IconTheme.JabRefIcon.PREFERENCES.getSmallIcon()); settings.add(andCb); settings.add(orCb); settings.addSeparator(); @@ -236,43 +227,36 @@ public void stateChanged(ChangeEvent e) { settings.addSeparator(); settings.add(showNumberOfElements); settings.add(autoAssignGroup); - // settings.add(moreRow); - // settings.add(lessRow); - openset.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - if (!settings.isVisible()) { - JButton src = (JButton) e.getSource(); - showNumberOfElements - .setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS)); - autoAssignGroup.setSelected(Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); - settings.show(src, 0, openset.getHeight()); - } + openSettings.addActionListener(e -> { + if (!settings.isVisible()) { + JButton src = (JButton) e.getSource(); + showNumberOfElements + .setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS)); + autoAssignGroup.setSelected(Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); + settings.show(src, 0, openSettings.getHeight()); } }); editModeCb.addActionListener(e -> setEditMode(editModeCb.getState())); + JButton newButton = new JButton(IconTheme.JabRefIcon.ADD_NOBOX.getSmallIcon()); int butSize = newButton.getIcon().getIconHeight() + 5; Dimension butDim = new Dimension(butSize, butSize); - //Dimension butDimSmall = new Dimension(20, 20); newButton.setPreferredSize(butDim); newButton.setMinimumSize(butDim); - refresh.setPreferredSize(butDim); - refresh.setMinimumSize(butDim); JButton helpButton = new HelpAction(Localization.lang("Help on groups"), HelpFiles.GROUP) .getHelpButton(); helpButton.setPreferredSize(butDim); helpButton.setMinimumSize(butDim); + JButton autoGroup = new JButton(IconTheme.JabRefIcon.AUTO_GROUP.getSmallIcon()); autoGroup.setPreferredSize(butDim); autoGroup.setMinimumSize(butDim); - openset.setPreferredSize(butDim); - openset.setMinimumSize(butDim); + openSettings.setPreferredSize(butDim); + openSettings.setMinimumSize(butDim); Insets butIns = new Insets(0, 0, 0, 0); helpButton.setMargin(butIns); - openset.setMargin(butIns); + openSettings.setMargin(butIns); newButton.addActionListener(e -> { GroupDialog gd = new GroupDialog(frame, panel, null); gd.setVisible(true); @@ -283,7 +267,6 @@ public void actionPerformed(ActionEvent e) { frame.output(Localization.lang("Created group \"%0\".", newGroup.getName())); } }); - refresh.addActionListener(e -> revalidateGroups()); andCb.addActionListener(e -> valueChanged(null)); orCb.addActionListener(e -> valueChanged(null)); invCb.addActionListener(e -> valueChanged(null)); @@ -300,10 +283,10 @@ public void actionPerformed(ActionEvent e) { hideNonHits.addActionListener(e -> valueChanged(null)); grayOut.addActionListener(e -> valueChanged(null)); newButton.setToolTipText(Localization.lang("New group")); - refresh.setToolTipText(Localization.lang("Refresh view")); andCb.setToolTipText(Localization.lang("Display only entries belonging to all selected groups.")); orCb.setToolTipText(Localization.lang("Display all entries belonging to one or more of the selected groups.")); autoGroup.setToolTipText(Localization.lang("Automatically create groups for database.")); + openSettings.setToolTipText(Localization.lang("Settings")); invCb.setToolTipText("" + Localization.lang("Show entries not in group selection") + ""); showOverlappingGroups.setToolTipText( Localization.lang("Highlight groups that contain entries contained in any currently selected group")); @@ -318,73 +301,48 @@ public void actionPerformed(ActionEvent e) { visMode.add(floatCb); visMode.add(highlCb); - JPanel main = new JPanel(); + JPanel rootPanel = new JPanel(); GridBagLayout gbl = new GridBagLayout(); - main.setLayout(gbl); + rootPanel.setLayout(gbl); GridBagConstraints con = new GridBagConstraints(); con.fill = GridBagConstraints.BOTH; - //con.insets = new Insets(0, 0, 2, 0); con.weightx = 1; con.gridwidth = 1; - con.gridx = 0; con.gridy = 0; - //con.insets = new Insets(1, 1, 1, 1); + + con.gridx = 0; gbl.setConstraints(newButton, con); - main.add(newButton); + rootPanel.add(newButton); + con.gridx = 1; - gbl.setConstraints(refresh, con); - main.add(refresh); - con.gridx = 2; gbl.setConstraints(autoGroup, con); - main.add(autoGroup); + rootPanel.add(autoGroup); + + con.gridx = 2; + gbl.setConstraints(openSettings, con); + rootPanel.add(openSettings); + con.gridx = 3; con.gridwidth = GridBagConstraints.REMAINDER; - gbl.setConstraints(helpButton, con); - main.add(helpButton); + rootPanel.add(helpButton); - // header.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.red)); - // helpButton.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.red)); groupsTree = new GroupsTree(this); groupsTree.addTreeSelectionListener(this); - JScrollPane sp = new JScrollPane(groupsTree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane groupsTreePane = new JScrollPane(groupsTree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + groupsTreePane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0)); con.gridwidth = GridBagConstraints.REMAINDER; con.weighty = 1; con.gridx = 0; con.gridwidth = 4; con.gridy = 1; - gbl.setConstraints(sp, con); - main.add(sp); - - JPanel pan = new JPanel(); - GridBagLayout gb = new GridBagLayout(); - con.weighty = 0; - gbl.setConstraints(pan, con); - pan.setLayout(gb); - con.insets = new Insets(0, 0, 0, 0); - con.gridx = 0; - con.gridy = 0; - con.weightx = 1; - con.gridwidth = 4; - con.fill = GridBagConstraints.HORIZONTAL; - gb.setConstraints(openset, con); - pan.add(openset); - - con.gridwidth = 6; - con.gridy = 1; - con.gridx = 0; - con.fill = GridBagConstraints.HORIZONTAL; + gbl.setConstraints(groupsTreePane, con); + rootPanel.add(groupsTreePane); - con.gridy = 2; - con.gridx = 0; - con.gridwidth = 4; - gbl.setConstraints(pan, con); - main.add(pan); - main.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); - add(main, BorderLayout.CENTER); + add(rootPanel, BorderLayout.CENTER); setEditMode(editModeIndicator); definePopup(); NodeAction moveNodeUpAction = new MoveNodeUpAction(); @@ -581,10 +539,12 @@ private void setEditMode(boolean editMode) { editModeIndicator = editMode; if (editMode) { - groupsTree.setBorder(editModeBorder); + groupsTree.setBorder(BorderFactory + .createTitledBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.RED), "Edit mode", + TitledBorder.RIGHT, TitledBorder.TOP, Font.getFont("Default"), Color.RED)); this.setTitle("Groups Edit mode"); } else { - groupsTree.setBorder(null); + groupsTree.setBorder(BorderFactory.createEmptyBorder(5,10,0,0)); this.setTitle(Localization.lang("Groups")); } groupsTree.revalidate(); From 247a98ef7d9c021d1dd5c0844873127c7f69a093 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 11 May 2016 21:15:55 +0200 Subject: [PATCH 073/268] Fix highlighting of matching groups As reported in https://github.com/JabRef/jabref/issues/1334#issuecomment-216045368 --- .../sf/jabref/gui/groups/GroupSelector.java | 11 ++++---- .../gui/groups/GroupTreeCellRenderer.java | 27 ++++++++++--------- .../net/sf/jabref/gui/groups/GroupsTree.java | 11 +++++--- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 284c36e085f4..b1bba1ce0020 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -27,6 +27,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Optional; @@ -1235,12 +1236,12 @@ public void setActiveBasePanel(BasePanel panel) { */ public void showMatchingGroups(List list, boolean requireAll) { if ((list == null) || (list.isEmpty())) { // nothing selected - groupsTree.setHighlight3Cells(null); + groupsTree.setMatchingGroups(Collections.emptyList()); groupsTree.revalidate(); return; } List nodeList = groupsRoot.getNode().getContainingGroups(list, requireAll); - groupsTree.setHighlight3Cells(nodeList.toArray()); + groupsTree.setMatchingGroups(nodeList); // ensure that all highlighted nodes are visible for (GroupTreeNode node : nodeList) { node.getParent().ifPresent( @@ -1250,11 +1251,11 @@ public void showMatchingGroups(List list, boolean requireAll) { } /** - * Show groups that, if selected, would show at least one of the entries found in the specified search. + * Show groups that, if selected, would show at least one of the entries in the specified list. */ - private void showOverlappingGroups(List matches) { //DatabaseSearch search) { + private void showOverlappingGroups(List matches) { List nodes = groupsRoot.getNode().getMatchingGroups(matches); - groupsTree.setHighlight2Cells(nodes.toArray()); + groupsTree.setHighlight2Cells(nodes); } public GroupsTree getGroupsTree() { diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java index e3b1d31fd31d..1fc6170577cc 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java @@ -17,6 +17,8 @@ import java.awt.Color; import java.awt.Component; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import javax.swing.BorderFactory; @@ -25,6 +27,7 @@ import javax.swing.JTree; import javax.swing.tree.DefaultTreeCellRenderer; +import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.util.strings.StringUtil; /** @@ -37,7 +40,7 @@ public class GroupTreeCellRenderer extends DefaultTreeCellRenderer { /** The cell over which the user is currently dragging */ private Object highlight1Cell; private Object[] highlight2Cells; - private Object[] highlight3Cells; + private List matchingGroups = new ArrayList<>(); private Object highlightBorderCell; @@ -66,7 +69,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean } Boolean red = printInRed(value); - Boolean underlined = printUnderlined(value); + Boolean underlined = printUnderlined(viewModel); StringBuilder sb = new StringBuilder(60); sb.append(""); if (red) { @@ -114,15 +117,12 @@ private boolean printInRed(Object value) { return false; } - private boolean printUnderlined(Object value) { - if (highlight3Cells != null) { - for (Object highlight3Cell : highlight3Cells) { - if (highlight3Cell.equals(value)) { - return true; - } - } + private boolean printUnderlined(GroupTreeNodeViewModel viewModel) { + if(viewModel.isAllEntriesGroup()) { + // Do not underline all entries group + return false; } - return false; + return matchingGroups.contains(viewModel.getNode()); } /** @@ -142,10 +142,11 @@ public void setHighlight2Cells(Object[] cells) { } /** - * Highlights the specified cells (by underlining), or disables highlight if cells == null. + * Highlights the specified groups by underlining. */ - public void setHighlight3Cells(Object[] cells) { - this.highlight3Cells = cells; + public void setMatchingGroups(List nodes) { + Objects.requireNonNull(nodes); + this.matchingGroups = nodes; } /** diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java index 66f642729805..db596ac6f507 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java @@ -39,6 +39,7 @@ import java.io.IOException; import java.util.Enumeration; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Vector; @@ -52,6 +53,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.EntriesGroupChange; +import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.groups.MoveGroupChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.util.Util; @@ -398,9 +400,12 @@ public void setHighlight2Cells(Object[] cells) { repaint(); } - /** Highlights the specified cells or disables highlight if cells == null */ - public void setHighlight3Cells(Object[] cells) { - localCellRenderer.setHighlight3Cells(cells); + /** + * Highlights the specified groups by underlining + **/ + public void setMatchingGroups(List nodes) { + Objects.requireNonNull(nodes); + localCellRenderer.setMatchingGroups(nodes); repaint(); } From 6d93ac0db3e54bdcba16f72f7c10bdcbcdfa0410 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 11 May 2016 21:29:03 +0200 Subject: [PATCH 074/268] Fix highlighting of overlapping groups --- .../sf/jabref/gui/groups/GroupSelector.java | 6 ++--- .../gui/groups/GroupTreeCellRenderer.java | 25 +++++++++---------- .../net/sf/jabref/gui/groups/GroupsTree.java | 9 ++++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index b1bba1ce0020..0640362689f7 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -162,7 +162,7 @@ public GroupSelector(JabRefFrame frame, SidePaneManager manager) { public void stateChanged(ChangeEvent event) { Globals.prefs.putBoolean(JabRefPreferences.GROUP_SHOW_OVERLAPPING, showOverlappingGroups.isSelected()); if (!showOverlappingGroups.isSelected()) { - groupsTree.setHighlight2Cells(null); + groupsTree.setOverlappingGroups(Collections.emptyList()); } } }); @@ -571,7 +571,7 @@ public void valueChanged(TreeSelectionEvent e) { if (getLeafsOfSelection().stream().allMatch(GroupTreeNodeViewModel::isAllEntriesGroup)) { panel.mainTable.getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); if (showOverlappingGroups.isSelected()) { - groupsTree.setHighlight2Cells(null); + groupsTree.setOverlappingGroups(Collections.emptyList()); } frame.output(Localization.lang("Displaying no groups") + "."); return; @@ -1255,7 +1255,7 @@ public void showMatchingGroups(List list, boolean requireAll) { */ private void showOverlappingGroups(List matches) { List nodes = groupsRoot.getNode().getMatchingGroups(matches); - groupsTree.setHighlight2Cells(nodes); + groupsTree.setOverlappingGroups(nodes); } public GroupsTree getGroupsTree() { diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java index 1fc6170577cc..23be5c0fb93e 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java @@ -39,7 +39,7 @@ public class GroupTreeCellRenderer extends DefaultTreeCellRenderer { /** The cell over which the user is currently dragging */ private Object highlight1Cell; - private Object[] highlight2Cells; + private List overlappingGroups = new ArrayList<>(); private List matchingGroups = new ArrayList<>(); private Object highlightBorderCell; @@ -68,7 +68,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean label.setBorder(BorderFactory.createEmptyBorder()); } - Boolean red = printInRed(value); + Boolean red = printInRed(viewModel) && !selected; // do not print currently selected node in red Boolean underlined = printUnderlined(viewModel); StringBuilder sb = new StringBuilder(60); sb.append(""); @@ -106,15 +106,13 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean return c; } - private boolean printInRed(Object value) { - if (highlight2Cells != null) { - for (Object highlight2Cell : highlight2Cells) { - if (highlight2Cell.equals(value)) { - return true; - } - } + private boolean printInRed(GroupTreeNodeViewModel viewModel) { + if(viewModel.isAllEntriesGroup()) { + // Do not print all entries group in red + return false; } - return false; + + return overlappingGroups.contains(viewModel.getNode()); } private boolean printUnderlined(GroupTreeNodeViewModel viewModel) { @@ -135,10 +133,11 @@ public void setHighlight1Cell(Object cell) { } /** - * Highlights the specified cells (in red), or disables highlight if cells == null. + * Highlights the specified groups in red. */ - public void setHighlight2Cells(Object[] cells) { - this.highlight2Cells = cells; + public void setOverlappingGroups(List nodes) { + Objects.requireNonNull(nodes); + this.overlappingGroups = nodes; } /** diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java index db596ac6f507..8d5508743804 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java @@ -394,9 +394,12 @@ private void setHighlight1Cell(Object cell) { repaint(); } - /** Highlights the specified cells or disables highlight if cells == null */ - public void setHighlight2Cells(Object[] cells) { - localCellRenderer.setHighlight2Cells(cells); + /** + * Highlights the specified groups in red + **/ + public void setOverlappingGroups(List nodes) { + Objects.requireNonNull(nodes); + localCellRenderer.setOverlappingGroups(nodes); repaint(); } From 2f1276857cd15881e315ebddda689349a451c182 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 11 May 2016 22:18:46 +0200 Subject: [PATCH 075/268] Fix #1122: Group view is immediately updated after adding an entry to a group Using the new and shiny event system --- CHANGELOG.md | 1 + .../java/net/sf/jabref/gui/BasePanel.java | 14 +++-- .../sf/jabref/model/database/BibDatabase.java | 21 ++++--- .../model/database/BibDatabaseTest.java | 60 +++++++------------ 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54942ac60c2f..1cd4e4ad6426 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1364](https://github.com/JabRef/jabref/issues/1364): Windows: install to LOCALAPPDATA directory for non-admin users - Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to `[auth][year]` - Fixed [#796](https://github.com/JabRef/jabref/issues/796): Undoing more than one entry at the same time is now working +- Fixed [#1122](https://github.com/JabRef/jabref/issues/1122): Group view is immediately updated after adding an entry to a group - Fixed [#1353](https://github.com/JabRef/jabref/issues/1353): Fetch-Preview did not display updated BibTeX-Key after clicking on `Generate Now` - Fixed [#1381](https://github.com/JabRef/jabref/issues/1381): File links containing blanks are broken if non-default viewer is set - Fixed sourceforge bug 1000: shorttitleINI can generate the initials of the shorttitle diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index ed59ef189881..a2dc4119889a 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -1252,14 +1252,11 @@ public SearchBar getSearchBar() { } - /** - * This listener is used to add a new entry to a group (or a set of groups) in case the Group View is selected and - * one or more groups are marked - */ private class GroupTreeListener { @Subscribe public void listen(EntryAddedEvent addedEntryEvent) { + // Automatically add new entry to the selected group (or set of groups) if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP) && frame.groupToggle.isSelected()) { final List entries = Collections.singletonList(addedEntryEvent.getBibEntry()); final TreePath[] selection = frame.getGroupSelector().getGroupsTree().getSelectionPaths(); @@ -1271,6 +1268,15 @@ public void listen(EntryAddedEvent addedEntryEvent) { } SwingUtilities.invokeLater(() -> BasePanel.this.getGroupSelector().valueChanged(null)); } + + // Update group display (for example to reflect that the number of contained entries has changed) + frame.getGroupSelector().revalidateGroups(); + } + + @Subscribe + public void listen(EntryChangedEvent entryChangedEvent) { + // Update group display in order to take changes into account + frame.getGroupSelector().revalidateGroups(); } } diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index fe04161dbba5..f4c4e7464555 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -43,13 +43,16 @@ import java.util.regex.Pattern; import net.sf.jabref.event.EntryAddedEvent; +import net.sf.jabref.event.EntryChangedEvent; import net.sf.jabref.event.EntryRemovedEvent; +import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.EntryUtil; import net.sf.jabref.model.entry.MonthUtil; import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -184,6 +187,8 @@ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionExcep internalIDs.add(id); entries.add(entry); + entry.registerListener(this); + eventBus.post(new EntryAddedEvent(entry)); return duplicationChecker.checkForDuplicateKeyAndAdd(null, entry.getCiteKey()); } @@ -549,18 +554,20 @@ public String getEpilog() { /** * Registers an listener object (subscriber) to the internal event bus. - * All subscribers should contain at least one @Subscribe annotated - * method accepting one of the following event types: + * The following events are posted: * * - {@link EntryAddedEvent} * - {@link EntryChangedEvent} * - {@link EntryRemovedEvent} * - * or another {@link EntryEvent} extending type. - * - * @param object Listener (subscriber) + * @param listener listener (subscriber) to add */ - public void registerListener(Object object) { - this.eventBus.register(object); + public void registerListener(Object listener) { + this.eventBus.register(listener); + } + + @Subscribe + private void relayEntryChangeEvent(FieldChangedEvent event) { + eventBus.post(event); } } diff --git a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java index d20ad5d70336..d1dbb56a4db4 100644 --- a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java +++ b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java @@ -15,7 +15,6 @@ import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.IdGenerator; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -33,22 +32,15 @@ public class BibDatabaseTest { @Rule public ExpectedException thrown = ExpectedException.none(); + private BibDatabase database; + @Before public void setUp() { Globals.prefs = JabRefPreferences.getInstance(); // set preferences for this test - } - @After - public void tearDown() { - Globals.prefs = null; + database = new BibDatabase(); } - /** - * Some basic test cases for resolving strings. - * - * @throws FileNotFoundException - * @throws IOException - */ @Test public void resolveStrings() throws IOException { try (FileInputStream stream = new FileInputStream("src/test/resources/net/sf/jabref/util/twente.bib"); @@ -67,10 +59,7 @@ public void resolveStrings() throws IOException { } @Test - public void insertEntry() { - BibDatabase database = new BibDatabase(); - assertEquals(Collections.emptyList(), database.getEntries()); - + public void insertEntryAddsEntryToEntriesList() { BibEntry entry = new BibEntry(); database.insertEntry(entry); assertEquals(database.getEntries().size(), 1); @@ -79,8 +68,7 @@ public void insertEntry() { } @Test - public void containsEntryId() { - BibDatabase database = new BibDatabase(); + public void containsEntryIdFindsEntry() { BibEntry entry = new BibEntry(); assertFalse(database.containsEntryWithId(entry.getId())); database.insertEntry(entry); @@ -89,8 +77,6 @@ public void containsEntryId() { @Test(expected = KeyCollisionException.class) public void insertEntryWithSameIdThrowsException() { - BibDatabase database = new BibDatabase(); - BibEntry entry0 = new BibEntry(); database.insertEntry(entry0); @@ -100,9 +86,7 @@ public void insertEntryWithSameIdThrowsException() { } @Test - public void removeEntry() { - BibDatabase database = new BibDatabase(); - + public void removeEntryRemovesEntryFromEntriesList() { BibEntry entry = new BibEntry(); database.insertEntry(entry); @@ -113,28 +97,24 @@ public void removeEntry() { @Test(expected = NullPointerException.class) public void insertNullEntryThrowsException() { - BibDatabase database = new BibDatabase(); database.insertEntry(null); fail(); } @Test(expected = NullPointerException.class) public void removeNullEntryThrowsException() { - BibDatabase database = new BibDatabase(); database.removeEntry(null); fail(); } @Test public void emptyDatabaseHasNoStrings() { - BibDatabase database = new BibDatabase(); assertEquals(Collections.emptySet(), database.getStringKeySet()); assertTrue(database.hasNoStrings()); } @Test - public void insertString() { - BibDatabase database = new BibDatabase(); + public void insertStringUpdatesStringList() { BibtexString string = new BibtexString(IdGenerator.next(), "DSP", "Digital Signal Processing"); database.addString(string); assertFalse(database.hasNoStrings()); @@ -146,8 +126,7 @@ public void insertString() { } @Test - public void insertAndRemoveString() { - BibDatabase database = new BibDatabase(); + public void removeStringUpdatesStringList() { BibtexString string = new BibtexString(IdGenerator.next(), "DSP", "Digital Signal Processing"); database.addString(string); database.removeString(string.getId()); @@ -160,8 +139,7 @@ public void insertAndRemoveString() { } @Test - public void hasStringLabel() { - BibDatabase database = new BibDatabase(); + public void hasStringLabelFindsString() { BibtexString string = new BibtexString(IdGenerator.next(), "DSP", "Digital Signal Processing"); database.addString(string); assertTrue(database.hasStringLabel("DSP")); @@ -170,7 +148,6 @@ public void hasStringLabel() { @Test(expected = KeyCollisionException.class) public void addSameStringLabelTwiceThrowsKeyCollisionException() { - BibDatabase database = new BibDatabase(); BibtexString string = new BibtexString(IdGenerator.next(), "DSP", "Digital Signal Processing"); database.addString(string); string = new BibtexString(IdGenerator.next(), "DSP", "Digital Signal Processor"); @@ -180,7 +157,6 @@ public void addSameStringLabelTwiceThrowsKeyCollisionException() { @Test(expected = KeyCollisionException.class) public void addSameStringIdTwiceThrowsKeyCollisionException() { - BibDatabase database = new BibDatabase(); String id = IdGenerator.next(); BibtexString string = new BibtexString(id, "DSP", "Digital Signal Processing"); database.addString(string); @@ -190,8 +166,7 @@ public void addSameStringIdTwiceThrowsKeyCollisionException() { } @Test - public void testAddedEntryEventReceivement() { - BibDatabase database = new BibDatabase(); + public void insertEntryPostsAddedEntryEvent() { BibEntry expectedEntry = new BibEntry(); TestEventListener tel = new TestEventListener(); database.registerListener(tel); @@ -201,8 +176,7 @@ public void testAddedEntryEventReceivement() { } @Test - public void testRemovedEntryEventReceivement() { - BibDatabase database = new BibDatabase(); + public void removeEntryPostsRemovedEntryEvent() { BibEntry expectedEntry = new BibEntry(); TestEventListener tel = new TestEventListener(); database.insertEntry(expectedEntry); @@ -211,4 +185,16 @@ public void testRemovedEntryEventReceivement() { BibEntry actualEntry = tel.getBibEntry(); assertEquals(expectedEntry, actualEntry); } + + @Test + public void changingEntryPostsChangeEntryEvent() { + BibEntry entry = new BibEntry(); + TestEventListener tel = new TestEventListener(); + database.insertEntry(entry); + database.registerListener(tel); + + entry.setField("test", "some value"); + + assertEquals(entry, tel.getBibEntry()); + } } From 7c8118a8931e49e55475fec0e28204a650e8ed6f Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 11 May 2016 22:45:20 +0200 Subject: [PATCH 076/268] Fix #171: Dragging an entry to a group preserves scrolling --- CHANGELOG.md | 3 ++- .../java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java | 2 +- src/main/java/net/sf/jabref/gui/groups/GroupsTree.java | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cd4e4ad6426..46966de59744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,8 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1364](https://github.com/JabRef/jabref/issues/1364): Windows: install to LOCALAPPDATA directory for non-admin users - Fixed [#1365](https://github.com/JabRef/jabref/issues/1365): Default label pattern back to `[auth][year]` - Fixed [#796](https://github.com/JabRef/jabref/issues/796): Undoing more than one entry at the same time is now working -- Fixed [#1122](https://github.com/JabRef/jabref/issues/1122): Group view is immediately updated after adding an entry to a group +- Fixed [#1122](https://github.com/JabRef/jabref/issues/1122): Group view is immediately updated after adding an entry to a group +- Fixed [#171](https://github.com/JabRef/jabref/issues/171): Dragging an entry to a group preserves scrolling - Fixed [#1353](https://github.com/JabRef/jabref/issues/1353): Fetch-Preview did not display updated BibTeX-Key after clicking on `Generate Now` - Fixed [#1381](https://github.com/JabRef/jabref/issues/1381): File links containing blanks are broken if non-default viewer is set - Fixed sourceforge bug 1000: shorttitleINI can generate the initials of the shorttitle diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java index cfc8b148c743..3d9c1fdb5369 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -326,7 +326,7 @@ public void changeEntriesTo(List entries, UndoManager undoManager) { undoRemove.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(this, changesAdd.get())); } undoManager.addEdit(undoRemove); - } else if (changesAdd != null) { + } else if (changesAdd.isPresent()) { undoManager.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(this, changesAdd.get())); } } diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java index 8d5508743804..b4176a41ab68 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java @@ -315,7 +315,6 @@ public void drop(DropTargetDropEvent dtde) { Optional undo = target.addEntriesToGroup(selection.getSelection()); if (undo.isPresent()) { dtde.getDropTargetContext().dropComplete(true); - groupSelector.revalidateGroups(); groupSelector.concludeAssignment(UndoableChangeEntriesOfGroup.getUndoableEdit(target, undo.get()), target.getNode(), assignedEntries); } From f501599313684647a1e1ef0c83b3028af4b2bf92 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 11 May 2016 22:52:25 +0200 Subject: [PATCH 077/268] Remove obsolete language key --- src/main/resources/l10n/JabRef_da.properties | 1 - src/main/resources/l10n/JabRef_de.properties | 1 - src/main/resources/l10n/JabRef_en.properties | 2 -- src/main/resources/l10n/JabRef_es.properties | 1 - src/main/resources/l10n/JabRef_fa.properties | 1 - src/main/resources/l10n/JabRef_fr.properties | 1 - src/main/resources/l10n/JabRef_in.properties | 1 - src/main/resources/l10n/JabRef_it.properties | 1 - src/main/resources/l10n/JabRef_ja.properties | 1 - src/main/resources/l10n/JabRef_nl.properties | 1 - src/main/resources/l10n/JabRef_no.properties | 1 - src/main/resources/l10n/JabRef_pt_BR.properties | 1 - src/main/resources/l10n/JabRef_ru.properties | 1 - src/main/resources/l10n/JabRef_sv.properties | 1 - src/main/resources/l10n/JabRef_tr.properties | 1 - src/main/resources/l10n/JabRef_vi.properties | 1 - src/main/resources/l10n/JabRef_zh.properties | 1 - 17 files changed, 18 deletions(-) diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 666dc5e2cf5b..07a1920c791b 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -594,7 +594,6 @@ Reference_database=Referencedatabase # The next two lines are used like in "References found\: 1 Number of references to fetch?" References_found=Referencer_fundet Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Undergruppe\:_Vis_poster_indeholdt_både_i_denne_gruppe_og_gruppe_over -Refresh_view=Opdater regular_expression=Regulærudtryk Remember_these_entry_types?=Husk_disse_posttyper? Remote_operation=Fjernstyring diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 80e841cd8d1d..071afa1f80c7 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1088,7 +1088,6 @@ References_found=Literaturangaben_gefunden Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Obergruppe_einbeziehen\:_Einträge_aus_dieser_Gruppe_und_ihrer_übergeordneten_Gruppe_anzeigen -Refresh_view=Ansicht_aktualisieren regular_expression=Regulärer_Ausdruck diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 278e2791ea59..cf59091eda5e 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1037,8 +1037,6 @@ References_found=References_found Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup -Refresh_view=Refresh_view - regular_expression=regular_expression Remember_these_entry_types?=Remember_these_entry_types? diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 195f95f3fd82..359218a19a07 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -554,7 +554,6 @@ Redo=Rehacer Reference_database=Base_de_datos_de_referencia References_found=Referencias_encontradas Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Refinar_supergrupo\:_Ver_entradas_contenidas_en_este_grupo_y_sus_subgrupos_cuando_estén_seleccionadas -Refresh_view=Refrescar_vista regular_expression=Expresión_Regular Remember_these_entry_types?=¿Recordar_estos_tipos_de_entrada? Remote_operation=Operación_remota diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 07f488b3d2af..ecbaaeebaa68 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1051,7 +1051,6 @@ References_found= Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup= -Refresh_view= regular_expression= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index fac4f5e2e3e8..4407a21cb811 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -554,7 +554,6 @@ Redo=Répéter Reference_database=Base_de_référence References_found=Références_trouvées Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Raffine_le_super-groupe_\:_Quand_sélectionné,_afficher_les_entrées_contenues_à_la_fois_dans_ce_groupe_et_son_super-groupe -Refresh_view=Rafraîchir_la_vue regular_expression=Expression_régulière Remember_these_entry_types?=Se_souvenir_de_ces_types_d'entrées_? Remote_operation=Accès_à_distance diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index b9875cc28a19..26e04e72316c 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -553,7 +553,6 @@ Redo=Mengembalikan Reference_database=Basisdata_acuan References_found=Acuan_ditemukan Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Perbaiki_supergrup\:_Ketika_dipilih,_lihat_entri_yang_ada_di_grup_ini_dan_supergrup -Refresh_view=Segarkan_tampilan regular_expression=Ekspresi_reguler Remember_these_entry_types?=Ingat_tipe_entri_ini? Remote_operation=Penggunaan_jarak_jauh diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 8d409539e4cb..21bd2e2d0916 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -603,7 +603,6 @@ Redo=Ripeti Reference_database=Database_di_riferimenti References_found=Riferimenti_trovati Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Perfeziona_il_super-gruppo\:_Quando_selezionato,_mostra_le_voci_contenute_sia_in_questo_gruppo_sia_nel_suo_super-gruppo -Refresh_view=Aggiorna_la_vista regular_expression=Espressione_regolare Remember_these_entry_types?=Ricordare_questo_tipo_di_voce? Remote_operation=Accesso_remoto diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 829aa7f42462..48a984ba37f5 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1069,7 +1069,6 @@ References_found=参照を検出 Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=上層グループの絞り込み:このグループとその上層グループの両方に含まれている項目を表示 -Refresh_view=表示を更新 regular_expression=正規表現 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 714bea10ba21..e227af3fcf29 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1086,7 +1086,6 @@ References_found=Referenties_gevonden Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Verfijn_supergroep\:_Wanneer_geselecteerd,_toon_de_entries_die_in_deze_groep_en_zijn_supergroep_zitten -Refresh_view=Beeld_verversen regular_expression=Regular_Expression diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 8fdb7c79ed52..1cfebe442755 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1167,7 +1167,6 @@ Reference_database=Referansedatabase References_found=Referanser_funnet Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Undergruppe\:_Vis_enheter_innehold_b\u00e5de_i_denne_gruppen_og_gruppen_over -Refresh_view=Oppdater regular_expression=Regul\u00e6ruttrykk diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index b1acfda3df39..3b6e5428a6da 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -554,7 +554,6 @@ Redo=Refazer Reference_database=Base_de_dados_de_referência References_found=Referências_encontradas Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Refinar_supergrupo\:_Quando_selecionado,_visualiza_referências_contidas_em_ambos_os_grupos_e_seu_supergrupo. -Refresh_view=Atualizar_a_visualização regular_expression=Expressão_regular Remember_these_entry_types?=Lembrar_destes_tipos_de_referências? Remote_operation=Operação_remota diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index bfe0992d58c0..ba2fa66af70d 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1052,7 +1052,6 @@ References_found=Найдены_ссылки Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Детализировать_супергруппу\:_Просмотр_записей,_содержащихся_в_группе_и_ее_супергруппе_(если_выбрано) -Refresh_view=Обновить_представление regular_expression=Регулярное_выражение diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 9327d3ee65f7..e61b9796b222 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -915,7 +915,6 @@ References=Referenser References_found= Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup= Refresh_OpenOffice/LibreOffice=Uppdatera_OpenOffice/LibreOffice -Refresh_view=Uppdatera_vyn Refuse_to_save_the_database_before_external_changes_have_been_reviewed.= Regenerate_all_keys_for_the_entries_in_a_BibTeX_file= Regenerating_BibTeX_keys_according_to_metadata= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 71f3c5e3a8f8..9ee99a848b07 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -554,7 +554,6 @@ Redo=Yeniden_yap Reference_database=Başvuru_veritabanı References_found=Bulunan_başvurular Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Supergrubu_arıt\:_Seçildiğinde,_hem_bu_grubun,_hem_de_süpergrubunun_içerdiği_girdileri_görüntüle -Refresh_view=Görünümü_tazele regular_expression=Düzenli_İfade Remember_these_entry_types?=Bu_girdi_türlerini_anımsa? Remote_operation=Uzak_işlem diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index d37810c83dec..e317847a7623 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1071,7 +1071,6 @@ References_found=Các_tài_liệu_tham_khảo_được_tìm_thấy Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Tinh_chỉnh_nhóm_lớn\:_Khi_được_chọn,_xem_các_mục_chứa_các_trong_nhóm_này_và_nhóm_lớn_của_nó -Refresh_view=Làm_tươi_lại_phần_xem regular_expression=Biểu_thức_chính_tắc diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 3cfdd7469e2e..234f61d0b1a9 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -561,7 +561,6 @@ Reference_database=参考文献数据库 References_found=找到参考文献 Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=提炼父分组:当分组被选中时,显示同时包含在该分组和它父分组中的记录 Refresh_OpenOffice/LibreOffice=刷新_penOffice/LibreOffice -Refresh_view=刷新视图 Regenerate_all_keys_for_the_entries_in_a_BibTeX_file=重新生成_BibTeX_文件中所有记录的键值 Regenerating_BibTeX_keys_according_to_metadata=基于_metadata_重新生成_BibTeX_键值 Remember_these_entry_types?=记住这些记录类型? From db7a319a22cf60483db2e37210eeaa851920534d Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 19 May 2016 11:31:16 +0200 Subject: [PATCH 078/268] Minimal refactoring --- src/main/java/net/sf/jabref/JabRefGUI.java | 11 +++++------ src/main/java/net/sf/jabref/JabRefMain.java | 6 ------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefGUI.java b/src/main/java/net/sf/jabref/JabRefGUI.java index c7b2616197cb..59ad7ff339fe 100644 --- a/src/main/java/net/sf/jabref/JabRefGUI.java +++ b/src/main/java/net/sf/jabref/JabRefGUI.java @@ -13,7 +13,6 @@ 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; import java.awt.Font; @@ -42,6 +41,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.preferences.LastFocusedTabPreferences; +import net.sf.jabref.logic.util.OS; import net.sf.jabref.migrations.PreferencesMigrations; import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; @@ -50,7 +50,6 @@ import org.apache.commons.logging.LogFactory; public class JabRefGUI { - private static final Log LOGGER = LogFactory.getLog(JabRefGUI.class); private static JabRefFrame mainFrame; @@ -62,7 +61,6 @@ public class JabRefGUI { private final List failed = new ArrayList<>(); private final List toOpenTab = new ArrayList<>(); - public JabRefGUI(List loaded, boolean isBlank) { this.loaded = loaded; this.isBlank = isBlank; @@ -75,9 +73,10 @@ private void openWindow() { PreferencesMigrations.upgradeSortOrder(); PreferencesMigrations.upgradeFaultyEncodingStrings(); - // This property is set to make the Mac OSX Java VM move the menu bar to - // the top of the screen, where Mac users expect it to be. - System.setProperty("apple.laf.useScreenMenuBar", "true"); + // This property is set to make the Mac OSX Java VM move the menu bar to the top of the screen + if (OS.OS_X) { + System.setProperty("apple.laf.useScreenMenuBar", "true"); + } // Set antialiasing on everywhere. This only works in JRE >= 1.5. // Or... it doesn't work, period. diff --git a/src/main/java/net/sf/jabref/JabRefMain.java b/src/main/java/net/sf/jabref/JabRefMain.java index 6253ff4141cf..62fc7c8e839a 100644 --- a/src/main/java/net/sf/jabref/JabRefMain.java +++ b/src/main/java/net/sf/jabref/JabRefMain.java @@ -13,7 +13,6 @@ 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; import java.net.Authenticator; @@ -40,16 +39,12 @@ * JabRef MainClass */ public class JabRefMain { - private static final Log LOGGER = LogFactory.getLog(JabRefMain.class); - public static void main(String[] args) { SwingUtilities.invokeLater(() -> start(args)); } - - private static void start(String[] args) { JabRefPreferences preferences = JabRefPreferences.getInstance(); @@ -112,5 +107,4 @@ private static void start(String[] args) { .invokeLater(() -> new JabRefGUI(argumentProcessor.getParserResults(), argumentProcessor.isBlank())); } - } From ed638e22a5b9eb4aa60d98c4143b296ebe49c86a Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 19 May 2016 13:43:35 +0200 Subject: [PATCH 079/268] Resolves #973 Add DOI field for English version of MS Office 2007 XML (#1410) * Resolves #973 Add DOI field for English version of MS Office 2007 XML * Changelog * Fix tests --- CHANGELOG.md | 1 + .../sf/jabref/exporter/MSBibExportFormat.java | 17 +++++++---------- .../net/sf/jabref/logic/msbib/MSBibEntry.java | 13 ++++++++++--- .../jabref/exporter/MsBibExportFormatTest2.bib | 5 +++-- .../jabref/exporter/MsBibExportFormatTest2.xml | 2 ++ .../jabref/exporter/MsBibExportFormatTest4.xml | 1 + .../resources/net/sf/jabref/exporter/test.xml | 16 ++++++++++++++++ 7 files changed, 40 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46966de59744..964ceb302cc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed sourceforge bug 1000: shorttitleINI can generate the initials of the shorttitle - Fixed [#1394](https://github.com/JabRef/jabref/issues/1394): Personal journal abbrevations could not be saved - Fixed [#1400](https://github.com/JabRef/jabref/issues/1400): Detect path constructs wrong path for Windows +- Fixed [#973](https://github.com/JabRef/jabref/issues/973): Add additional DOI field for English version of MS Office 2007 XML ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java b/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java index 980a54f02f9e..3ff579d185b4 100644 --- a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java @@ -49,19 +49,16 @@ public void performExport(final BibDatabaseContext databaseContext, final String Objects.requireNonNull(databaseContext); Objects.requireNonNull(entries); - if (entries.isEmpty()) { // Only export if entries exist + if (entries.isEmpty()) { return; } - // forcing to use UTF8 output format for some problems with - // xml export in other encodings - SaveSession ss = new SaveSession(StandardCharsets.UTF_8, false); - MSBibDatabase md = new MSBibDatabase(databaseContext.getDatabase(), entries); - try (VerifyingWriter ps = ss.getWriter()) { - - // PS: DOES NOT SUPPORT EXPORTING ONLY A SET OF ENTRIES + // forcing to use UTF8 output format for some problems with xml export in other encodings + SaveSession session = new SaveSession(StandardCharsets.UTF_8, false); + MSBibDatabase msBibDatabase = new MSBibDatabase(databaseContext.getDatabase(), entries); + try (VerifyingWriter ps = session.getWriter()) { try { - DOMSource source = new DOMSource(md.getDOMrepresentation()); + DOMSource source = new DOMSource(msBibDatabase.getDOMrepresentation()); StreamResult result = new StreamResult(ps); Transformer trans = TransformerFactory.newInstance().newTransformer(); trans.setOutputProperty(OutputKeys.INDENT, "yes"); @@ -69,7 +66,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String } catch (TransformerException | IllegalArgumentException | TransformerFactoryConfigurationError e) { throw new Error(e); } - finalizeSaveSession(ss, new File(file)); + finalizeSaveSession(session, new File(file)); } catch (SaveException | IOException ex) { throw new IOException(ex.getMessage()); } diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java index 5a3ff1a5b233..26766f2b3669 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java @@ -108,6 +108,7 @@ class MSBibEntry { private String thesisType; private String internetSiteTitle; private String dateAccessed; + private String doi; private String url; private String productionCompany; private String publicationTitle; @@ -267,6 +268,7 @@ private void populateFromXml(Element entry, String bcol) { dateAccessed = null; } + doi = getFromXml(bcol + "DOI", entry); url = getFromXml(bcol + "URL", entry); productionCompany = getFromXml(bcol + "ProductionCompany", entry); @@ -434,8 +436,11 @@ private void populateFromBibtex(BibEntry bibtex) { if (bibtex.hasField(MSBIB + "accessed")) { dateAccessed = bibtex.getField(MSBIB + "accessed"); } + if (bibtex.hasField("doi")) { + doi = bibtex.getField("doi"); + } if (bibtex.hasField("url")) { - url = bibtex.getField("url"); /* SM: 2010.10: lower case */ + url = bibtex.getField("url"); } if (bibtex.hasField(MSBIB + "productioncompany")) { productionCompany = bibtex.getField(MSBIB + "productioncompany"); @@ -539,14 +544,12 @@ private void populateFromBibtex(BibEntry bibtex) { // http://www.microsoft.com/globaldev/reference/lcid-all.mspx private int getLCID(String language) { // TODO: add language to LCID mapping - return 0; } // http://www.microsoft.com/globaldev/reference/lcid-all.mspx private String getLanguage(int LCID) { // TODO: add language to LCID mapping - return "english"; } @@ -797,6 +800,7 @@ public Element getDOMrepresentation(Document document) { /* SM 2010.10 added month export */ addField(document, msbibEntry, "Month", month); + addField(document, msbibEntry, "DOI", doi); addField(document, msbibEntry, "URL", url); addField(document, msbibEntry, "ProductionCompany", productionCompany); addField(document, msbibEntry, "PublicationTitle", publicationTitle); @@ -1007,6 +1011,9 @@ public BibEntry getBibtexRepresentation() { if (dateAccessed != null) { hm.put(MSBIB + "accessed", dateAccessed); } + if (doi != null) { + hm.put("doi", doi); + } if (url != null) { hm.put("url", url); } diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib index ef5214ba7a3f..5b771c4c5912 100644 --- a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib @@ -1,14 +1,15 @@ @phdthesis{2002, title = {Agile Entwicklung Web-basierter Systeme}, year = {2002}, - type = {type}, + type = {type}, number = {3}, - address = {a}, + address = {a}, journal = {Wirtschaftsinformatik}, keywords = {software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development}, language = {english}, pages = {237--248}, publisher = {Gabler Verlag}, + doi = {10.1007/BF03250842}, url = {http://dx.doi.org/10.1007/BF03250842}, volume = {44}, } diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml index 99b753ce23a7..2f47866a2f5e 100644 --- a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml @@ -10,11 +10,13 @@ 237-248 44 + DOI: 10.1007/BF03250842 Gabler Verlag a Wirtschaftsinformatik 3 type +10.1007/BF03250842 http://dx.doi.org/10.1007/BF03250842 software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml index d35b5b92ddc4..9719402e2cfd 100644 --- a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml @@ -14,6 +14,7 @@ Gabler Verlag Wirtschaftsinformatik 3 +10.1000/182 http://dx.doi.org/10.1007/BF03250842 software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development diff --git a/src/test/resources/net/sf/jabref/exporter/test.xml b/src/test/resources/net/sf/jabref/exporter/test.xml index fd9958930afb..3cbf4c63a0fd 100644 --- a/src/test/resources/net/sf/jabref/exporter/test.xml +++ b/src/test/resources/net/sf/jabref/exporter/test.xml @@ -17,6 +17,7 @@ 3075-3080 +http://doi.acm.org/10.1145/1358628.1358810 ISBN: 978-1-60558-012-X DOI: http://doi.acm.org/10.1145/1358628.1358810 ACM New York, NY, USA @@ -40,6 +41,7 @@ 13-14 34 +http://doi.acm.org/10.1145/820127.820136 ISSN: 0097-8418 DOI: http://doi.acm.org/10.1145/820127.820136 ACM New York, NY, USA @@ -72,6 +74,7 @@ 10-12 12 +http://dx.doi.org/10.1109/MIC.2008.67 ISSN: 1089-7801 DOI: http://dx.doi.org/10.1109/MIC.2008.67 IEEE Educational Activities Department Piscataway @@ -126,6 +129,7 @@ 25-31 2 +http://dx.doi.org/10.1109/MSP.2004.81 ISSN: 1540-7993 DOI: http://dx.doi.org/10.1109/MSP.2004.81 IEEE Educational Activities Department Piscataway @@ -151,6 +155,7 @@ 357-367 9 +http://dx.doi.org/10.1007/s00779-005-0347-6 ISSN: 1617-4909 DOI: http://dx.doi.org/10.1007/s00779-005-0347-6 Springer-Verlag London @@ -192,6 +197,7 @@ 11-18 +http://doi.acm.org/10.1145/1137627.1137631 ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137631 ACM New York, NY, USA @@ -219,6 +225,7 @@ 529-530 +http://doi.acm.org/10.1145/1233341.1233448 ISBN: 978-1-59593-629-5 DOI: http://doi.acm.org/10.1145/1233341.1233448 ACM New York, NY, USA @@ -257,6 +264,7 @@ 25-31 2 +http://dx.doi.org/10.1109/MSP.2004.81 ISSN: 1540-7993 DOI: http://dx.doi.org/10.1109/MSP.2004.81 IEEE Educational Activities Department Piscataway @@ -286,6 +294,7 @@ 199-203 +http://doi.acm.org/10.1145/1132736.1132768 ISBN: 1-59593-350-6 DOI: http://doi.acm.org/10.1145/1132736.1132768 ACM New York, NY, USA @@ -350,6 +359,7 @@ 429-432 +http://doi.acm.org/10.1145/1182475.1182529 ISBN: 1-59593-325-5 DOI: http://doi.acm.org/10.1145/1182475.1182529 ACM New York, NY, USA @@ -378,6 +388,7 @@ 51-58 +http://doi.acm.org/10.1145/1137627.1137636 ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137636 ACM New York, NY, USA @@ -406,6 +417,7 @@ 90-94 +http://doi.acm.org/10.1145/1314276.1314293 ISBN: 978-1-59593-884-8 DOI: http://doi.acm.org/10.1145/1314276.1314293 ACM New York, NY, USA @@ -438,6 +450,7 @@ 1-2 +http://doi.acm.org/10.1145/1137627.1137628 ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137628 ACM New York, NY, USA @@ -494,6 +507,7 @@ 25-34 +http://doi.acm.org/10.1145/1073001.1073004 ISBN: 1-59593-178-3 DOI: http://doi.acm.org/10.1145/1073001.1073004 ACM New York, NY, USA @@ -526,6 +540,7 @@ 27-34 +http://doi.acm.org/10.1145/1137627.1137633 ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137633 ACM New York, NY, USA @@ -576,6 +591,7 @@ 1-7 +http://doi.acm.org/10.1145/1143120.1143122 ISBN: 1-59593-448-0 DOI: http://doi.acm.org/10.1145/1143120.1143122 ACM New York, NY, USA From c4a99cfa3d303bac58799af3e24237ff3d47b724 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 20 May 2016 00:24:12 +0200 Subject: [PATCH 080/268] Fix #1342: Show description of case converters as tooltip --- CHANGELOG.md | 1 + .../sf/jabref/gui/fieldeditors/contextmenu/CaseChangeMenu.java | 1 + .../sf/jabref/gui/fieldeditors/contextmenu/ConversionMenu.java | 1 + 3 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 964ceb302cc0..d2a31cb738f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Integrity check table can be sorted by clicking on column headings - Added \SOFTWARE\Jabref 'Path' registry entry for installation path inside the installer - Added an additional icon to distinguish DOI and URL links ([feature request #696](https://github.com/JabRef/jabref/issues/696)) +- Implemented [#1342](https://github.com/JabRef/jabref/issues/1342): show description of case converters as tooltip ### Fixed - Fixed [#473](https://github.com/JabRef/jabref/issues/473): Values in an entry containing symbols like ' are now properly escaped for exporting to the database diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/CaseChangeMenu.java b/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/CaseChangeMenu.java index dda4a844d6c0..1652d9ff5551 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/CaseChangeMenu.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/CaseChangeMenu.java @@ -34,6 +34,7 @@ public CaseChangeMenu(final JTextComponent parent) { // create menu items, one for each case changer for (final Formatter caseChanger : Formatters.CASE_CHANGERS) { JMenuItem menuItem = new JMenuItem(caseChanger.getName()); + menuItem.setToolTipText(caseChanger.getDescription()); menuItem.addActionListener(e -> parent.setText(caseChanger.format(parent.getText()))); this.add(menuItem); } diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/ConversionMenu.java b/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/ConversionMenu.java index 29e907352fcb..61463a755632 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/ConversionMenu.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/contextmenu/ConversionMenu.java @@ -37,6 +37,7 @@ public ConversionMenu(JTextComponent opener) { // create menu items, one for each case changer for (Formatter converter : Formatters.CONVERTERS) { JMenuItem menuItem = new JMenuItem(converter.getName()); + menuItem.setToolTipText(converter.getDescription()); menuItem.addActionListener(e -> opener.setText(converter.format(opener.getText()))); this.add(menuItem); } From e5d5c72b087d20a86d8306b36d13bec897860144 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 20 May 2016 11:23:14 +0200 Subject: [PATCH 081/268] Fix HTML Inspired by the result of https://www.talater.com/open-source-templates/ For other issue templates see https://github.com/devspace/awesome-github-templates --- .github/ISSUE_TEMPLATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 986d0195a057..8dcd05a16e22 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ -JabRef version on - +JabRef version on + Steps to reproduce: @@ -7,4 +7,4 @@ Steps to reproduce: 2. ... 3. ... - + From ba831eedf2366f0e7e8eaf840208cfb49a0de232 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 20 May 2016 11:23:49 +0200 Subject: [PATCH 082/268] Fix HTML --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e05771a4f960..91b9058ff7e4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,4 @@ - + - [ ] Change in CHANGELOG.md described - [ ] Tests created for changes From b84ad3b8f880cdce6071b5fd322f37b9d9dffa48 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Fri, 20 May 2016 11:38:11 +0200 Subject: [PATCH 083/268] Refactor Gradle script * Include localization tasks and package into a group * Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- build.gradle | 1 + localization.gradle | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a74084930e70..7fefc2013be9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,7 +99,7 @@ because . Add new Localization.lang("KEY") to Java file. Tests fail. In the test output a snippet is generated which must be added to the English translation file. There is also a snippet generated for the non-English files, but this is irrelevant. Add snippet to English translation file located at `src/main/resources/l10n/JabRef_en.properties` -With `gradlew -b localization.gradle generateMissingTranslationKeys` the "KEY" is added to the other translation files as well. +With `gradlew generateMissingTranslationKeys` the "KEY" is added to the other translation files as well. Tests are green again. You can also directly run the specific test in your IDE. The test "LocalizationConsistencyTest" is placed under `src/test/java/net.sf.jabref.logic.l10n/LocalizationConsistencyTest.java` diff --git a/build.gradle b/build.gradle index 48e0a27b55df..78ba85ff62f4 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,7 @@ apply plugin: 'me.champeau.gradle.jmh' apply plugin: 'checkstyle' apply from: 'eclipse.gradle' +apply from: 'localization.gradle' group = "net.sf.jabref" version = "3.4dev" diff --git a/localization.gradle b/localization.gradle index 5122a008a19f..22d5415fc643 100644 --- a/localization.gradle +++ b/localization.gradle @@ -12,6 +12,7 @@ dependencies { task checkTranslations(type: JavaExec) { description "Print empty and duplicate translations." + group = 'Localization' main 'org.python.util.jython' classpath project.configurations.jython.asPath args file("scripts/syncLang.py") @@ -20,6 +21,7 @@ task checkTranslations(type: JavaExec) { task checkTranslationsSummary(type: JavaExec) { description "Print summary of empty and duplicate translations." + group = 'Localization' main 'org.python.util.jython' classpath project.configurations.jython.asPath args file("scripts/syncLang.py") @@ -28,6 +30,7 @@ task checkTranslationsSummary(type: JavaExec) { task showMissingTranslationKeys(type: JavaExec) { description "Prints differences between the English translation and translations in other languages." + group = 'Localization' main 'org.python.util.jython' classpath project.configurations.jython.asPath args file("scripts/syncLang.py") @@ -36,6 +39,7 @@ task showMissingTranslationKeys(type: JavaExec) { task generateMissingTranslationKeys(type: JavaExec) { description "Prints differences between the English translation and translations in other languages, and updates translations if possible." + group = 'Localization' main 'org.python.util.jython' classpath project.configurations.jython.asPath args file("scripts/syncLang.py") From 9021933fbc989cb5ca04b7c9aae87ea36ae4158d Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Fri, 20 May 2016 11:41:54 +0200 Subject: [PATCH 084/268] Resolve #1417 Rename buttons in file list editor from auto->get fulltext, download->download from URL --- .../java/net/sf/jabref/gui/fieldeditors/FileListEditor.java | 4 ++-- src/main/resources/l10n/JabRef_da.properties | 4 ++++ src/main/resources/l10n/JabRef_de.properties | 4 ++++ src/main/resources/l10n/JabRef_en.properties | 4 ++-- src/main/resources/l10n/JabRef_es.properties | 4 ++++ src/main/resources/l10n/JabRef_fa.properties | 4 ++++ src/main/resources/l10n/JabRef_fr.properties | 4 ++++ src/main/resources/l10n/JabRef_in.properties | 4 ++++ src/main/resources/l10n/JabRef_it.properties | 4 ++++ src/main/resources/l10n/JabRef_ja.properties | 4 ++++ src/main/resources/l10n/JabRef_nl.properties | 4 ++++ src/main/resources/l10n/JabRef_no.properties | 4 ++++ src/main/resources/l10n/JabRef_pt_BR.properties | 4 ++++ src/main/resources/l10n/JabRef_ru.properties | 4 ++++ src/main/resources/l10n/JabRef_sv.properties | 4 ++++ src/main/resources/l10n/JabRef_tr.properties | 4 ++++ src/main/resources/l10n/JabRef_vi.properties | 4 ++++ src/main/resources/l10n/JabRef_zh.properties | 4 ++++ 18 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java b/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java index 1128e81182bc..3c5ca5bf0bd3 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java @@ -115,8 +115,8 @@ public FileListEditor(JabRefFrame frame, BibDatabaseContext databaseContext, Str JButton up = new JButton(IconTheme.JabRefIcon.UP.getSmallIcon()); JButton down = new JButton(IconTheme.JabRefIcon.DOWN.getSmallIcon()); - auto = new JButton(Localization.lang("Auto")); - JButton download = new JButton(Localization.lang("Download")); + auto = new JButton(Localization.lang("Get fulltext")); + JButton download = new JButton(Localization.lang("Download from URL")); add.setMargin(new Insets(0, 0, 0, 0)); remove.setMargin(new Insets(0, 0, 0, 0)); up.setMargin(new Insets(0, 0, 0, 0)); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 07a1920c791b..8643c8b07f1e 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1684,3 +1684,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 071afa1f80c7..4d0d2104ed80 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2400,3 +2400,7 @@ Copy_version_to_clipboard=Kopiere_Version_in_die_Zwischenablage Copied_version_to_clipboard=Version_in_die_Zwischenablage_kopiert BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index cf59091eda5e..c374d186b851 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -622,7 +622,7 @@ Generate_now=Generate_now Generated_BibTeX_key_for=Generated_BibTeX_key_for Generating_BibTeX_key_for=Generating_BibTeX_key_for - +Get_fulltext=Get_fulltext Grab=Grab Gray_out_entries_not_in_group_selection=Gray_out_entries_not_in_group_selection @@ -1513,7 +1513,7 @@ Line_%0\:_Found_corrupted_BibTeX_key_(comma_missing).=Line_%0\:_Found_corrupted_ Finished_downloading_full_text_document=Finished_downloading_full_text_document Full_text_document_download_failed=Full_text_document_download_failed Update_to_current_column_order=Update_to_current_column_order - +Download_from_URL=Download_from_URL Rename_field=Rename_field Set/clear/rename_fields=Set/clear/rename_fields Rename_field_to=Rename_field_to diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 359218a19a07..dd8608017494 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1585,3 +1585,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index ecbaaeebaa68..ea86f56cc262 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2371,3 +2371,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 4407a21cb811..9e060a6bdb3b 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1629,3 +1629,7 @@ booktitle_ends_with_'conference_on'=le_titre_d'ouvrage_se_termine_par_'conferenc BibTeX_key=Clef_BibTeX Message=Message + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 26e04e72316c..668972b1f6c2 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1604,3 +1604,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 21bd2e2d0916..8793202a2f6d 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1704,3 +1704,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 48a984ba37f5..8ccf4bcd9d1e 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2349,3 +2349,7 @@ Copied_version_to_clipboard=クリップボードにコピーされたバージ booktitle_ends_with_'conference_on'= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index e227af3fcf29..2b557bfcc286 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2380,3 +2380,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 1cfebe442755..fa0b17d0de37 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2776,3 +2776,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 3b6e5428a6da..1be1de4017a5 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1598,3 +1598,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index ba2fa66af70d..9b7e3f2586f7 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2348,3 +2348,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index e61b9796b222..6606b3ab555f 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1543,3 +1543,7 @@ Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 9ee99a848b07..7a2b9766095d 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1617,3 +1617,7 @@ Copied_version_to_clipboard=Sürüm_panoya_kopyalandı BibTeX_key=BibTeX_anahtarı Message=Mesaj + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index e317847a7623..340f4ddf9e8a 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2372,3 +2372,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 234f61d0b1a9..1265a5184d3a 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1611,3 +1611,7 @@ Copy_version_to_clipboard= Copied_version_to_clipboard= BibTeX_key= Message= + +Get_fulltext= + +Download_from_URL= From 2bd4c4ac17edfb3fba5b6b344b40426289d63860 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 20 May 2016 20:10:55 +0200 Subject: [PATCH 085/268] Remove Groups -> Settings -> Select Matches (#1427) --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/JabRefPreferences.java | 2 -- src/main/java/net/sf/jabref/gui/groups/GroupSelector.java | 7 ------- src/main/resources/l10n/JabRef_da.properties | 2 -- src/main/resources/l10n/JabRef_de.properties | 2 -- src/main/resources/l10n/JabRef_en.properties | 4 ---- src/main/resources/l10n/JabRef_es.properties | 2 -- src/main/resources/l10n/JabRef_fa.properties | 2 -- src/main/resources/l10n/JabRef_fr.properties | 2 -- src/main/resources/l10n/JabRef_in.properties | 2 -- src/main/resources/l10n/JabRef_it.properties | 2 -- src/main/resources/l10n/JabRef_ja.properties | 2 -- src/main/resources/l10n/JabRef_nl.properties | 2 -- src/main/resources/l10n/JabRef_no.properties | 2 -- src/main/resources/l10n/JabRef_pt_BR.properties | 2 -- src/main/resources/l10n/JabRef_ru.properties | 2 -- src/main/resources/l10n/JabRef_sv.properties | 2 -- src/main/resources/l10n/JabRef_tr.properties | 2 -- src/main/resources/l10n/JabRef_vi.properties | 2 -- src/main/resources/l10n/JabRef_zh.properties | 2 -- 20 files changed, 1 insertion(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2a31cb738f5..6fefbcd836f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Removed possibility to automatically add braces via Option - Preferences - File - Store the following fields with braces around capital letters. Please use save actions instead for adding braces automatically. - Removed button to refresh groups view. This button shouldn't be needed anymore. Please report any cases where the groups view is not updated automatically. - Medline and GVK importer no longer try to expand author initials (i.e. `EH Wissler -> E. H. Wissler`). +- Removed not-working option "Select Matches" under Groups -> Settings. diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index bbbd74c289d0..c95e8603fd03 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -195,7 +195,6 @@ public class JabRefPreferences { public static final String GROUP_SHOW_DYNAMIC = "groupShowDynamic"; public static final String GROUP_SHOW_ICONS = "groupShowIcons"; public static final String GROUPS_DEFAULT_FIELD = "groupsDefaultField"; - public static final String GROUP_SELECT_MATCHES = "groupSelectMatches"; public static final String GROUP_SHOW_OVERLAPPING = "groupShowOverlapping"; public static final String GROUP_INVERT_SELECTIONS = "groupInvertSelections"; public static final String GROUP_INTERSECT_SELECTIONS = "groupIntersectSelections"; @@ -605,7 +604,6 @@ private JabRefPreferences() { defaults.put(GROUP_INTERSECT_SELECTIONS, Boolean.TRUE); defaults.put(GROUP_INVERT_SELECTIONS, Boolean.FALSE); defaults.put(GROUP_SHOW_OVERLAPPING, Boolean.FALSE); - defaults.put(GROUP_SELECT_MATCHES, Boolean.FALSE); defaults.put(GROUPS_DEFAULT_FIELD, "keywords"); defaults.put(GROUP_SHOW_ICONS, Boolean.TRUE); defaults.put(GROUP_SHOW_DYNAMIC, Boolean.TRUE); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 0640362689f7..4650c9b44778 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -102,7 +102,6 @@ public class GroupSelector extends SidePaneComponent implements TreeSelectionLis private final JRadioButtonMenuItem andCb = new JRadioButtonMenuItem(Localization.lang("Intersection"), true); private final JRadioButtonMenuItem floatCb = new JRadioButtonMenuItem(Localization.lang("Float"), true); private final JCheckBoxMenuItem invCb = new JCheckBoxMenuItem(Localization.lang("Inverted"), false); - private final JCheckBoxMenuItem select = new JCheckBoxMenuItem(Localization.lang("Select matches"), false); private final JCheckBoxMenuItem showOverlappingGroups = new JCheckBoxMenuItem( Localization.lang("Highlight overlapping groups")); private final JCheckBoxMenuItem showNumberOfElements = new JCheckBoxMenuItem( @@ -167,7 +166,6 @@ public void stateChanged(ChangeEvent event) { } }); - select.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_SELECT_MATCHES, select.isSelected())); grayOut.addChangeListener(event -> Globals.prefs.putBoolean(JabRefPreferences.GRAY_OUT_NON_HITS, grayOut.isSelected())); JRadioButtonMenuItem highlCb = new JRadioButtonMenuItem(Localization.lang("Highlight"), false); @@ -205,7 +203,6 @@ public void stateChanged(ChangeEvent e) { invCb.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_INVERT_SELECTIONS)); showOverlappingGroups.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_OVERLAPPING)); - select.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SELECT_MATCHES)); editModeIndicator = Globals.prefs.getBoolean(JabRefPreferences.EDIT_GROUP_MEMBERSHIP_MODE); editModeCb.setSelected(editModeIndicator); showNumberOfElements.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS)); @@ -217,8 +214,6 @@ public void stateChanged(ChangeEvent e) { settings.addSeparator(); settings.add(invCb); settings.addSeparator(); - settings.add(select); - settings.addSeparator(); settings.add(editModeCb); settings.addSeparator(); settings.add(grayOut); @@ -280,7 +275,6 @@ public void stateChanged(ChangeEvent e) { }); floatCb.addActionListener(e -> valueChanged(null)); highlCb.addActionListener(e -> valueChanged(null)); - select.addActionListener(e -> valueChanged(null)); hideNonHits.addActionListener(e -> valueChanged(null)); grayOut.addActionListener(e -> valueChanged(null)); newButton.setToolTipText(Localization.lang("New group")); @@ -293,7 +287,6 @@ public void stateChanged(ChangeEvent e) { Localization.lang("Highlight groups that contain entries contained in any currently selected group")); floatCb.setToolTipText(Localization.lang("Move entries in group selection to the top")); highlCb.setToolTipText(Localization.lang("Gray out entries not in group selection")); - select.setToolTipText(Localization.lang("Select entries in group selection")); editModeCb.setToolTipText(Localization.lang("Click group to toggle membership of selected entries")); ButtonGroup bgr = new ButtonGroup(); bgr.add(andCb); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 8643c8b07f1e..e6fa85d381b5 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -666,11 +666,9 @@ Select_action=Vælg_handling Select_all=Vælg_alle Select_Classpath_of_New_Importer=Vælg_classpath_for_nyt_importformat Select_encoding=Vælg_tegnkodning -Select_entries_in_group_selection=Vælg_poster_i_valgte_grupper Select_entry_type=Vælg_posttype Select_external_application=Vælg_ekstern_applikation Select_file_from_ZIP-archive=Vælg_fil_fra_ZIP-fil -Select_matches=Vælg_match Select_new_ImportFormat_Subclass=Vælg_klasse_til_nyt_importformat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Vælg_forgreningerne_for_at_inspicere_og_acceptere_eller_forkaste_ændringer Selected_entries=Valgte_poster diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 4d0d2104ed80..e3db4c5d1f8e 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1236,7 +1236,6 @@ Select_Classpath_of_New_Importer=Klassenpfad_auswählen Select_encoding=Kodierung_wählen -Select_entries_in_group_selection=Wähle_Einträge_in_Gruppenauswahl Select_entry_type=Eintragstyp_auswählen Select_external_application=Externe_Anwendung_auswählen @@ -1244,7 +1243,6 @@ Select_external_application=Externe_Anwendung_auswählen Select_file_from_ZIP-archive=Eintrag_aus_der_ZIP-Archiv_auswählen -Select_matches=Treffer_auswählen Select_new_ImportFormat_Subclass=Klasse_auswählen diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index c374d186b851..a12aa039044d 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1168,15 +1168,11 @@ Select_Classpath_of_New_Importer=Select_Classpath_of_New_Importer Select_encoding=Select_encoding -Select_entries_in_group_selection=Select_entries_in_group_selection - Select_entry_type=Select_entry_type Select_external_application=Select_external_application Select_file_from_ZIP-archive=Select_file_from_ZIP-archive -Select_matches=Select_matches - Select_new_ImportFormat_Subclass=Select_new_ImportFormat_Subclass Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Select_the_tree_nodes_to_view_and_accept_or_reject_changes diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index dd8608017494..a0d9f6d049ee 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -622,11 +622,9 @@ Select_action=Seleccionar_acción Select_all=Seleccionar_todo Select_Classpath_of_New_Importer=Seleccionar_classpath_del_nuevo_importador Select_encoding=Seleccionar_codificación -Select_entries_in_group_selection=Seleccionar_entradas_dentro_de_la_selección_de_grupo Select_entry_type=Seleccionar_tipo_de_entrada Select_external_application=Seleccionar_aplicación_externa Select_file_from_ZIP-archive=Seleccionar_archivo_desde_archivo_ZIP -Select_matches=Seleccionar_coincidencias Select_new_ImportFormat_Subclass=Seleccionar_nueva_subclase_de_formato_de_importación Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Seleccionar_nodos_de_árbol_para_ver_y_aceptar_o_rechazar_los_cambios. Selected_entries=Entradas_seleccionadas diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index ea86f56cc262..cbec249fc1b5 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1199,7 +1199,6 @@ Select_Classpath_of_New_Importer= Select_encoding= -Select_entries_in_group_selection= Select_entry_type= Select_external_application= @@ -1207,7 +1206,6 @@ Select_external_application= Select_file_from_ZIP-archive= -Select_matches= Select_new_ImportFormat_Subclass= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 9e060a6bdb3b..3ff6a2635295 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -622,11 +622,9 @@ Select_action=Sélectionner_l'opération Select_all=Tout_sélectionner Select_Classpath_of_New_Importer=Sélectionner_le_chemin_de_classe_du_nouveau_fil7tre_d'importation Select_encoding=Sélectionner_l'encodage -Select_entries_in_group_selection=Sélectionner_les_entrées_dans_la_sélection Select_entry_type=Sélectionner_un_type_d'entrée Select_external_application=Sélectionner_une_application_externe Select_file_from_ZIP-archive=Sélectionner_un_fichier_depuis_une_archive_ZIP -Select_matches=Sélectionner_les_correspondances Select_new_ImportFormat_Subclass=Sélectionner_une_nouvelle_sous-classe_ImportFormat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Sélectionner_les_noeuds_de_l'arborescence_pour_voir,_et_accepter_ou_rejeter,_les_modifications Selected_entries=Les_entrées_sélectionnées diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 668972b1f6c2..815cd8b7c09f 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -621,11 +621,9 @@ Select_action=Pilih_aksi Select_all=Pilih_semua Select_Classpath_of_New_Importer=Pilih_Classpath_dari_Pengimpor_Baru Select_encoding=Pilih_enkoding -Select_entries_in_group_selection=Pilih_entri_dalam_grup_pilihan Select_entry_type=Pilih_tipe_entri Select_external_application=Pilih_aplikasi_eksternal Select_file_from_ZIP-archive=Pilih_berkas_dari_arsip_ZIP -Select_matches=Pilih_matches Select_new_ImportFormat_Subclass=Pilih_ImportFormat_Subclass_baru Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Pilih_tiga_nodal_untuk_melihat,_menerima_atau_menolak_perubahan Selected_entries=Entri_pilihan diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 8793202a2f6d..ab79f6d78767 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -678,11 +678,9 @@ Select_action=Seleziona_l'operazione Select_all=Seleziona_tutto Select_Classpath_of_New_Importer=Seleziona_il_classpath_del_nuovo_filtro_di_importazione Select_encoding=Seleziona_la_codifica -Select_entries_in_group_selection=Seleziona_le_voci_nella_selezione_dei_gruppi Select_entry_type=Seleziona_un_tipo_di_voce Select_external_application=Seleziona_un'applicazione_esterna Select_file_from_ZIP-archive=Seleziona_un_file_da_un_archivio_Zip -Select_matches=Seleziona_le_corrispondenze Select_new_ImportFormat_Subclass=Seleziona_una_nuova_sottoclasse_ImportFormat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Selezionare_i_nodi_dell'albero_per_vedere_ed_accettare_o_rifiutare_le_modifiche Selected_entries=Voci_selezionate diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 8ccf4bcd9d1e..434ea286037b 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1217,7 +1217,6 @@ Select_Classpath_of_New_Importer=新しい読み込みのクラスパスを選 Select_encoding=エンコーディングを選択 -Select_entries_in_group_selection=グループ選択にある項目を選択する Select_entry_type=項目型を選択してください Select_external_application=外部アプリケーションを選択 @@ -1225,7 +1224,6 @@ Select_external_application=外部アプリケーションを選択 Select_file_from_ZIP-archive=ZIP書庫からファイルを選択してください -Select_matches=一致したものを選択 Select_new_ImportFormat_Subclass=新しいImportFormatサブクラスを選択 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 2b557bfcc286..8493ea103304 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1234,7 +1234,6 @@ Select_Classpath_of_New_Importer=Selecteer_Classpath_van_Nieuwe_Importer Select_encoding=Selecteer_encodering -Select_entries_in_group_selection=Selecteer_entries_in_groep_selectie Select_entry_type=Selecteer_entry_type Select_external_application=Selecteer_externe_applicatie @@ -1242,7 +1241,6 @@ Select_external_application=Selecteer_externe_applicatie Select_file_from_ZIP-archive=Selecteer_bestand_van_ZIP-archief -Select_matches=Selecteer_overeenkomsten Select_new_ImportFormat_Subclass=Selecteer_nieuw_ImportFormat_Subklasse diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index fa0b17d0de37..08ee7d9c0611 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1322,7 +1322,6 @@ Select_Classpath_of_New_Importer=Velg_classpath_for_nytt_importformat Select_encoding=Velg_koding -Select_entries_in_group_selection=Velg_enheter_i_valgte_grupper Select_entry_type=Velg_enhetstype @@ -1332,7 +1331,6 @@ Select_file_from_ZIP-archive=Velg_fil_fra_ZIP-fil -Select_matches=Velg_treff Select_new_ImportFormat_Subclass=Velg_klasse_for_nytt_importformat diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 1be1de4017a5..fe35567b5ebf 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -622,11 +622,9 @@ Select_action=Selecionar_operação Select_all=Selecionar_tudo Select_Classpath_of_New_Importer=Selecionar_classpath_para_o_novo_filtro_de_importação Select_encoding=Selecionar_codificação -Select_entries_in_group_selection=Selecionar_referências_no_grupo_selecionado Select_entry_type=Selecionar_tipo_de_referência Select_external_application=Selecionar_aplicação_externa Select_file_from_ZIP-archive=Selecionar_arquivo_a_partir_de_um_arquivo_ZIP -Select_matches=Selecionar_correspondências Select_new_ImportFormat_Subclass=Selecionar_nova_subclasse_ImportFormat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Selecione_os_nós_da_árvore_para_visualizar_e_aceitar_ou_rejeitar_mudanças Selected_entries=Referências_selecionadas diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 9b7e3f2586f7..3fc1069a8429 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1191,7 +1191,6 @@ Select_Classpath_of_New_Importer=Выбрать_путь_класса_для_н Select_encoding=Выбрать_кодировку -Select_entries_in_group_selection=Выбрать_записи_в_выбранной_группе Select_entry_type=Выбрать_тип_записи Select_external_application=Выбрать_внешнее_приложение @@ -1199,7 +1198,6 @@ Select_external_application=Выбрать_внешнее_приложение Select_file_from_ZIP-archive=Выбрать_файл_из_ZIP-архива -Select_matches=Выбрать_соответствия Select_new_ImportFormat_Subclass=Выбрать_новый_подкласс_ImportFormat diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 6606b3ab555f..9c1b7e41d437 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1034,14 +1034,12 @@ Select_at_least_one_entry_to_manage_keywords.=Välj_åtminstone_en_post_för_att Select_directory=Välj_mapp Select_document=Välj_dokument Select_encoding=Välj_teckenkodning -Select_entries_in_group_selection= Select_entry_type=Välj_posttyp Select_export_format= Select_external_application=Välj_program Select_file_from_ZIP-archive=Välj_fil_från_Zip-arkiv Select_file_type\:=Välj_filtyp\: Select_files=Välj_filer -Select_matches=Välj_sökträffar Select_new_ImportFormat_Subclass= Select_one_entry.=Välj_en_post. Select_style=Välj_stil diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 7a2b9766095d..0fdeac046d5f 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -622,11 +622,9 @@ Select_action=Eylem_seç Select_all=Tümünü_seç Select_Classpath_of_New_Importer=Yeni_İçe_Aktarıcının_Sınıfyolunu_seç Select_encoding=Kodlamayı_seç -Select_entries_in_group_selection=Grup_seçimindeki_girdileri_seç Select_entry_type=Girdi_türünü_seç Select_external_application=Harici_uygulamayı_seç Select_file_from_ZIP-archive=ZIP_arşivinden_dosyayı_seçiniz -Select_matches=Eşleşenleri_seçiniz Select_new_ImportFormat_Subclass=Yeni_İçe_Aktarım_Biçemi_Altsınıfını_seçiniz Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Değişiklikleri_görmek_ve_kabul_ya_da_reddetmek_için_ağaç_düğümlerini_seçiniz Selected_entries=Seçili_girdiler diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 340f4ddf9e8a..1644fb3422e2 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1219,7 +1219,6 @@ Select_Classpath_of_New_Importer=Chọn_đường_dẫn_lớp_của_trình_nhậ Select_encoding=Chọn_bộ_mã_hóa -Select_entries_in_group_selection=Chọn_các_mục_trong_phép_chọn_nhóm Select_entry_type=Chọn_kiểu_mục Select_external_application=Chọn_ứng_dụng_ngoài @@ -1227,7 +1226,6 @@ Select_external_application=Chọn_ứng_dụng_ngoài Select_file_from_ZIP-archive=Chọn_tập_tin_từ_tập_tin_Zip -Select_matches=Chọn_các_mục_khớp Select_new_ImportFormat_Subclass=Chọn_Lớp.phụ_Định.dạng.nhập_mới diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 1265a5184d3a..5982ba1afbc3 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -635,11 +635,9 @@ Select_a_Zip-archive=选择一个_Zip_压缩包 Select_action=选择操作 Select_all=全选 Select_encoding=选择编码 -Select_entries_in_group_selection=选中选中分组中的记录 Select_entry_type=选择记录类型 Select_external_application=选择外部程序 Select_file_from_ZIP-archive=从_ZIP-压缩包中选择文件 -Select_matches=选中匹配的记录 Select_new_ImportFormat_Subclass=选择新的_ImportFormat_子类 Select_the_tree_nodes_to_view_and_accept_or_reject_changes=选择树节点查看和接受/拒绝修改 Selected_entries=选中的记录 From 60bef24bd61638a153065e7c0341ae5ef63d665f Mon Sep 17 00:00:00 2001 From: Koji Yokota Date: Mon, 23 May 2016 00:17:03 +0900 Subject: [PATCH 086/268] Updating Japanese localization Updating JabRef_ja.properties and Menu_ja.properties. --- src/main/resources/l10n/JabRef_ja.properties | 22 ++++++++++---------- src/main/resources/l10n/Menu_ja.properties | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 434ea286037b..d266fbb4c570 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -238,8 +238,8 @@ Clear_fields=フィールドを消去 Close=閉じる -Close_Others= -Close_All= +Close_Others=他を閉じる +Close_All=すべて閉じる Close_dialog=ダイアログを閉じる Close_the_current_database=現在のデータベースを閉じる @@ -751,7 +751,7 @@ Inverted=否定 ISO_abbreviation=ISO短縮形 -Online_help= +Online_help=オンラインヘルプ JabRef_preferences=JabRefの設定 @@ -788,7 +788,7 @@ LaTeX_AUX_file=LaTeX_AUXファイル Leave_file_in_its_current_directory=ファイルを現在のディレクトリに置いておく。 Left=左 -Level= +Level=レベル Limit_to_fields=以下のフィールドに制限 @@ -955,7 +955,7 @@ Open_last_edited_databases_at_startup=起動時に最後に編集していたデ Open_right-click_menu_with_Ctrl+left_button=Ctrl+左ボタンで右クリックメニューを開く -Open_terminal_here= +Open_terminal_here=ここで端末を開く Open_URL_or_DOI=URLまたはDOIを開く @@ -2123,7 +2123,7 @@ Proxy_requires_authentication=プロキシには認証が必要 Always_reformat_.bib_file_on_save_and_export=保存・書出の際、つねに.bibファイルを再整形する Allow_overwriting_existing_links.=既存リンクの上書きを許可する。 Do_not_overwrite_existing_links.=既存リンクは上書きしない。 -Disable_highlight_groups_matching_entries= +Disable_highlight_groups_matching_entries=項目に一致するグループの着色を無効化 New_%0_database=新規%0データベース Export_sorting=整序法を書き出す No_entry_found_for_ISBN_%0_at_www.ebook.de=www.ebook.deにISBN_%0に一致する項目は見つかりませんでした @@ -2344,10 +2344,10 @@ Syntax_error_in_regular-expression_pattern=正規表現パターン中の文法 Copy_version_to_clipboard=バージョンをクリップボードにコピー Copied_version_to_clipboard=クリップボードにコピーされたバージョン -booktitle_ends_with_'conference_on'= -BibTeX_key= -Message= +booktitle_ends_with_'conference_on'=「conference_on」で終わるbooktitle +BibTeX_key=BibTeX鍵 +Message=メッセージ -Get_fulltext= +Get_fulltext=フルテキストを得る -Download_from_URL= +Download_from_URL=URLからダウンロード diff --git a/src/main/resources/l10n/Menu_ja.properties b/src/main/resources/l10n/Menu_ja.properties index 3a77d1d752f8..4a2b1cdd9e16 100644 --- a/src/main/resources/l10n/Menu_ja.properties +++ b/src/main/resources/l10n/Menu_ja.properties @@ -134,4 +134,4 @@ Quality=品質 New_%0_database=新しい%0データベース -Disable_highlight_groups_matching_entries=項目に一致するグループのハイライトを無効化 +Disable_highlight_groups_matching_entries=項目に一致するグループの着色を無効化 From 1e644d3865bf9e74eb46417c47e536f5cf171f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lenhard?= Date: Mon, 23 May 2016 11:49:35 +0200 Subject: [PATCH 087/268] Cleanup guiglobals (#1409) * Move constants from GUIGlobals with only single usages to the classes where they are used * Add kau address to mail aliases * Move LatexFieldFormatter to the bibtex package * Turn MAX_BACK_HISTORY_SIZE into preference * Turn LINE_LENGTH into preference * Move back frame colors to GUIGlobals * Move back NULL_FIELD_COLOR to GUIGlobals * Move back ACTIVE_EDITOR_COLOR to GUIGlobals * Turn INDENT into preference * Move back WIDTH_ICON_COL_RANKING to GUIGlobals * Move FieldContentParser to bibtex package * Move bibtex pacakge into logic * Add debugging output to failing test * Ignore sonargraph files * Ensure that customn entry types are always removed * Move back COL_DEFINITION_FIELD_SEPARATOR to GUIGlobals * Improve naming and sorting of constants in ExportCustomizationDialog * Improve naming of constants in ImportCustomizationDialog * Inline unnecessary variable in SidePane * Move from GUIGlobals to Globals --- .gitignore | 1 + .mailmap | 1 + src/main/java/net/sf/jabref/Globals.java | 4 ++ src/main/java/net/sf/jabref/JabRefMain.java | 2 +- .../java/net/sf/jabref/JabRefPreferences.java | 14 ++++-- .../net/sf/jabref/collab/ChangeScanner.java | 2 +- .../sf/jabref/exporter/BibDatabaseWriter.java | 13 ++--- .../exporter/ExportCustomizationDialog.java | 12 +++-- .../sf/jabref/exporter/OOCalcDatabase.java | 4 +- .../exporter/OpenDocumentRepresentation.java | 4 +- .../net/sf/jabref/exporter/SaveSession.java | 6 ++- .../java/net/sf/jabref/gui/BasePanel.java | 7 ++- .../jabref/gui/EntryCustomizationDialog.java | 2 +- .../java/net/sf/jabref/gui/EntryMarker.java | 2 +- .../sf/jabref/gui/FieldContentSelector.java | 5 +- .../java/net/sf/jabref/gui/GUIGlobals.java | 47 +++---------------- .../sf/jabref/gui/ImportInspectionDialog.java | 6 +-- .../java/net/sf/jabref/gui/JabRefFrame.java | 11 +++-- .../sf/jabref/gui/SaveOrderConfigDisplay.java | 2 +- src/main/java/net/sf/jabref/gui/SidePane.java | 2 +- .../java/net/sf/jabref/gui/StringDialog.java | 4 +- .../jabref/gui/TransferableBibtexEntry.java | 4 +- .../cleanup/FieldFormatterCleanupsPanel.java | 2 +- .../jabref/gui/entryeditor/EntryEditor.java | 12 +++-- .../gui/entryeditor/EntryEditorTab.java | 4 +- .../gui/entryeditor/FieldExtraComponents.java | 4 +- .../gui/keyboard/KeyBindingsDialog.java | 8 ++-- .../sf/jabref/gui/maintable/MainTable.java | 6 +-- .../jabref/gui/maintable/MainTableColumn.java | 7 +-- .../jabref/gui/maintable/MainTableFormat.java | 6 +-- .../PersistenceTableColumnListener.java | 2 +- .../maintable/SpecialMainTableColumns.java | 2 +- .../sf/jabref/gui/menus/RightClickMenu.java | 2 +- .../jabref/gui/mergeentries/MergeEntries.java | 4 +- .../sf/jabref/gui/openoffice/OOBibBase.java | 4 +- .../gui/plaintextimport/TextInputDialog.java | 8 ++-- .../jabref/gui/preftabs/TableColumnsTab.java | 4 +- .../sf/jabref/gui/preftabs/TablePrefsTab.java | 2 +- .../gui/search/SearchResultsDialog.java | 8 ++-- .../jabref/gui/worker/SendAsEMailAction.java | 4 +- .../importer/ImportCustomizationDialog.java | 22 +++++---- .../importer/fileformat/BibtexParser.java | 5 +- .../autocompleter/AutoCompleterFactory.java | 4 +- .../{ => logic}/bibtex/BibEntryWriter.java | 5 +- .../bibtex}/FieldContentParser.java | 6 +-- .../bibtex}/LatexFieldFormatter.java | 11 ++--- .../comparator/BibtexStringComparator.java | 2 +- .../comparator/CrossRefEntryComparator.java | 2 +- .../bibtex/comparator/EntryComparator.java | 6 +-- .../bibtex/comparator/FieldComparator.java | 10 ++-- .../comparator/FieldComparatorStack.java | 2 +- .../logic/integrity/IntegrityCheck.java | 4 +- .../net/sf/jabref/logic/util/UpdateField.java | 2 +- .../sf/jabref/logic/xmp/XMPSchemaBibtex.java | 4 +- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 4 +- .../net/sf/jabref/model/DuplicateCheck.java | 4 +- .../entry}/BibtexSingleField.java | 2 +- .../entry}/FieldProperties.java | 2 +- .../entry}/InternalBibtexFields.java | 3 +- src/main/java/net/sf/jabref/sql/SQLUtil.java | 2 +- src/main/java/net/sf/jabref/util/Util.java | 2 +- .../exporter/BibDatabaseWriterTest.java | 34 ++++++++------ .../importer/fetcher/GVKParserTest.java | 2 +- .../fileformat/BibTeXMLImporterTestFiles.java | 2 +- .../BiblioscapeImporterTestFiles.java | 2 +- .../fileformat/CopacImporterTestFiles.java | 2 +- .../importer/fileformat/InspecImportTest.java | 2 +- .../fileformat/MedlinePlainImporterTest.java | 2 +- .../fileformat/MsBibImporterTestfiles.java | 2 +- .../importer/fileformat/OvidImporterTest.java | 2 +- .../PdfContentImporterTestFiles.java | 2 +- .../fileformat/RISImporterTestFiles.java | 2 +- .../fileformat/RepecNepImporterTest.java | 2 +- .../fileformat/SilverPlatterImporterTest.java | 2 +- .../{ => logic}/bibtex/BibEntryAssert.java | 2 +- .../bibtex/BibEntryWriterTest.java | 3 +- .../bibtex/EntryTypesTestBibLatex.java | 2 +- .../bibtex/EntryTypesTestBibtex.java | 6 ++- .../bibtex}/FieldContentParserTest.java | 2 +- .../bibtex}/LatexFieldFormatterTests.java | 5 +- .../BibtexStringComparatorTest.java | 2 +- .../logic/integrity/IntegrityCheckTest.java | 2 +- .../net/sf/jabref/logic/xmp/XMPUtilTest.java | 4 +- .../model/entry/IEEETranEntryTypesTest.java | 2 - 84 files changed, 215 insertions(+), 221 deletions(-) rename src/main/java/net/sf/jabref/{ => logic}/bibtex/BibEntryWriter.java (98%) rename src/main/java/net/sf/jabref/{importer/fileformat => logic/bibtex}/FieldContentParser.java (92%) rename src/main/java/net/sf/jabref/{exporter => logic/bibtex}/LatexFieldFormatter.java (97%) rename src/main/java/net/sf/jabref/{ => logic}/bibtex/comparator/BibtexStringComparator.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/bibtex/comparator/CrossRefEntryComparator.java (97%) rename src/main/java/net/sf/jabref/{ => logic}/bibtex/comparator/EntryComparator.java (97%) rename src/main/java/net/sf/jabref/{ => logic}/bibtex/comparator/FieldComparator.java (95%) rename src/main/java/net/sf/jabref/{ => logic}/bibtex/comparator/FieldComparatorStack.java (97%) rename src/main/java/net/sf/jabref/{bibtex => model/entry}/BibtexSingleField.java (99%) rename src/main/java/net/sf/jabref/{bibtex => model/entry}/FieldProperties.java (92%) rename src/main/java/net/sf/jabref/{bibtex => model/entry}/InternalBibtexFields.java (99%) rename src/test/java/net/sf/jabref/{ => logic}/bibtex/BibEntryAssert.java (99%) rename src/test/java/net/sf/jabref/{ => logic}/bibtex/BibEntryWriterTest.java (99%) rename src/test/java/net/sf/jabref/{ => logic}/bibtex/EntryTypesTestBibLatex.java (97%) rename src/test/java/net/sf/jabref/{ => logic}/bibtex/EntryTypesTestBibtex.java (88%) rename src/test/java/net/sf/jabref/{importer/fileformat => logic/bibtex}/FieldContentParserTest.java (97%) rename src/test/java/net/sf/jabref/{exporter => logic/bibtex}/LatexFieldFormatterTests.java (97%) rename src/test/java/net/sf/jabref/{ => logic}/bibtex/comparator/BibtexStringComparatorTest.java (97%) diff --git a/.gitignore b/.gitignore index 255904bcfe77..68d80273720c 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ bin/ # UNKNWON jabref.xml install4j6/ +*.sonargraph diff --git a/.mailmap b/.mailmap index 79fc629da8f9..f91b578b66f9 100644 --- a/.mailmap +++ b/.mailmap @@ -84,6 +84,7 @@ Lee Patton Jörg Lenhard + Matthias Geiger Christoph Braun Felix Wilke diff --git a/src/main/java/net/sf/jabref/Globals.java b/src/main/java/net/sf/jabref/Globals.java index 1fe930e94af9..bd77eec76ed0 100644 --- a/src/main/java/net/sf/jabref/Globals.java +++ b/src/main/java/net/sf/jabref/Globals.java @@ -37,6 +37,10 @@ public class Globals { // Signature written at the top of the .bib file. public static final String SIGNATURE = "This file was created with JabRef"; public static final String ENCODING_PREFIX = "Encoding: "; + // Character separating field names that are to be used in sequence as + // fallbacks for a single column (e.g. "author/editor" to use editor where + // author is not set): + public static final String COL_DEFINITION_FIELD_SEPARATOR = "/"; // Newlines // will be overridden in initialization due to feature #857 @ JabRef.java public static String NEWLINE = System.lineSeparator(); diff --git a/src/main/java/net/sf/jabref/JabRefMain.java b/src/main/java/net/sf/jabref/JabRefMain.java index 62fc7c8e839a..1754bc8b9451 100644 --- a/src/main/java/net/sf/jabref/JabRefMain.java +++ b/src/main/java/net/sf/jabref/JabRefMain.java @@ -19,7 +19,6 @@ import javax.swing.SwingUtilities; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.cli.ArgumentProcessor; import net.sf.jabref.exporter.ExportFormats; import net.sf.jabref.gui.remote.JabRefMessageHandler; @@ -31,6 +30,7 @@ import net.sf.jabref.logic.net.ProxyRegisterer; import net.sf.jabref.logic.remote.RemotePreferences; import net.sf.jabref.logic.remote.client.RemoteListenerClient; +import net.sf.jabref.model.entry.InternalBibtexFields; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index c95e8603fd03..bbdc6e774213 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -45,12 +45,10 @@ import javax.swing.JTable; import javax.swing.UIManager; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.exporter.CustomExportList; import net.sf.jabref.exporter.ExportComparator; import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.external.DroppedFileHandler; -import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; import net.sf.jabref.gui.maintable.PersistenceTableColumnListener; @@ -75,12 +73,14 @@ import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.specialfields.SpecialFieldsUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class JabRefPreferences { + private static final Log LOGGER = LogFactory.getLog(JabRefPreferences.class); public static final String EXTERNAL_FILE_TYPES = "externalFileTypes"; @@ -263,6 +263,9 @@ public class JabRefPreferences { public static final String ACTIVE_PREVIEW = "activePreview"; public static final String PREVIEW_ENABLED = "previewEnabled"; public static final String MERGE_ENTRIES_DIFF_MODE = "mergeEntriesDiffMode"; + public static final String MAX_BACK_HISTORY_SIZE = "maxBackHistorySize"; // The maximum number of "Back" operations stored. + public static final String LINE_LENGTH = "lineLength"; // Maximum + public static final String INDENT = "indent"; // Indent for formatted bibtex output. public static final String CUSTOM_EXPORT_FORMAT = "customExportFormat"; public static final String CUSTOM_IMPORT_FORMAT = "customImportFormat"; @@ -557,7 +560,7 @@ private JabRefPreferences() { PersistenceTableColumnListener.DEFAULT_ENABLED); defaults.put(XMP_PRIVACY_FILTERS, "pdf;timestamp;keywords;owner;note;review"); defaults.put(USE_XMP_PRIVACY_FILTER, Boolean.FALSE); - defaults.put(NUMBER_COL_WIDTH, GUIGlobals.NUMBER_COL_LENGTH); + defaults.put(NUMBER_COL_WIDTH, 32); defaults.put(WORKING_DIRECTORY, USER_HOME); defaults.put(EXPORT_WORKING_DIRECTORY, USER_HOME); // Remembers working directory of last import @@ -630,7 +633,7 @@ private JabRefPreferences() { defaults.put(FONT_SIZE, 12); defaults.put(OVERRIDE_DEFAULT_FONTS, Boolean.FALSE); defaults.put(MENU_FONT_SIZE, 11); - defaults.put(TABLE_ROW_PADDING, GUIGlobals.TABLE_ROW_PADDING); + defaults.put(TABLE_ROW_PADDING, 9); defaults.put(TABLE_SHOW_GRID, Boolean.FALSE); // Main table color settings: defaults.put(TABLE_BACKGROUND, "255:255:255"); @@ -854,6 +857,9 @@ private JabRefPreferences() { defaults.put(USE_CONVERT_TO_EQUATION, Boolean.FALSE); defaults.put(USE_CASE_KEEPER_ON_SEARCH, Boolean.TRUE); defaults.put(USE_UNIT_FORMATTER_ON_SEARCH, Boolean.TRUE); + defaults.put(MAX_BACK_HISTORY_SIZE, 10); + defaults.put(LINE_LENGTH, 65); + defaults.put(INDENT, 4); } public String getUser() { diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index edb8ac72ed4f..77c082a4553b 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -34,7 +34,6 @@ import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.bibtex.comparator.EntryComparator; import net.sf.jabref.exporter.BibDatabaseWriter; import net.sf.jabref.exporter.SaveException; import net.sf.jabref.exporter.SavePreferences; @@ -43,6 +42,7 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.importer.OpenDatabaseAction; import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.logic.bibtex.comparator.EntryComparator; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.DuplicateCheck; diff --git a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java index 0a16e2842f78..a735aa410882 100644 --- a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -35,12 +35,13 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.MetaData; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.bibtex.comparator.BibtexStringComparator; -import net.sf.jabref.bibtex.comparator.CrossRefEntryComparator; -import net.sf.jabref.bibtex.comparator.FieldComparator; -import net.sf.jabref.bibtex.comparator.FieldComparatorStack; import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.comparator.BibtexStringComparator; +import net.sf.jabref.logic.bibtex.comparator.CrossRefEntryComparator; +import net.sf.jabref.logic.bibtex.comparator.FieldComparator; +import net.sf.jabref.logic.bibtex.comparator.FieldComparatorStack; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.logic.id.IdComparator; import net.sf.jabref.logic.util.strings.StringUtil; diff --git a/src/main/java/net/sf/jabref/exporter/ExportCustomizationDialog.java b/src/main/java/net/sf/jabref/exporter/ExportCustomizationDialog.java index 0e3624b6267a..f9a0edc299da 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/exporter/ExportCustomizationDialog.java @@ -38,7 +38,6 @@ import javax.swing.table.TableColumnModel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFiles; @@ -61,6 +60,11 @@ public class ExportCustomizationDialog extends JDialog { + // Column widths for export customization dialog table: + private static final int COL_0_WIDTH = 50; + private static final int COL_1_WIDTH = 200; + private static final int COL_2_WIDTH = 30; + public ExportCustomizationDialog(final JabRefFrame frame) { super(frame, Localization.lang("Manage custom exports"), false); @@ -68,9 +72,9 @@ public ExportCustomizationDialog(final JabRefFrame frame) { Globals.prefs.customExports.getSortedList(), new ExportTableFormat()); JTable table = new JTable(tableModel); TableColumnModel cm = table.getColumnModel(); - cm.getColumn(0).setPreferredWidth(GUIGlobals.EXPORT_DIALOG_COL_0_WIDTH); - cm.getColumn(1).setPreferredWidth(GUIGlobals.EXPORT_DIALOG_COL_1_WIDTH); - cm.getColumn(2).setPreferredWidth(GUIGlobals.EXPORT_DIALOG_COL_2_WIDTH); + cm.getColumn(0).setPreferredWidth(COL_0_WIDTH); + cm.getColumn(1).setPreferredWidth(COL_1_WIDTH); + cm.getColumn(2).setPreferredWidth(COL_2_WIDTH); JScrollPane sp = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); diff --git a/src/main/java/net/sf/jabref/exporter/OOCalcDatabase.java b/src/main/java/net/sf/jabref/exporter/OOCalcDatabase.java index 9f0216476952..9c4a34ead008 100644 --- a/src/main/java/net/sf/jabref/exporter/OOCalcDatabase.java +++ b/src/main/java/net/sf/jabref/exporter/OOCalcDatabase.java @@ -22,8 +22,8 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import net.sf.jabref.bibtex.comparator.FieldComparator; -import net.sf.jabref.bibtex.comparator.FieldComparatorStack; +import net.sf.jabref.logic.bibtex.comparator.FieldComparator; +import net.sf.jabref.logic.bibtex.comparator.FieldComparatorStack; import net.sf.jabref.logic.layout.format.GetOpenOfficeType; import net.sf.jabref.logic.layout.format.RemoveBrackets; import net.sf.jabref.logic.layout.format.RemoveWhitespace; diff --git a/src/main/java/net/sf/jabref/exporter/OpenDocumentRepresentation.java b/src/main/java/net/sf/jabref/exporter/OpenDocumentRepresentation.java index 67c39e9691d0..b03e6daa0b1c 100644 --- a/src/main/java/net/sf/jabref/exporter/OpenDocumentRepresentation.java +++ b/src/main/java/net/sf/jabref/exporter/OpenDocumentRepresentation.java @@ -22,8 +22,8 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import net.sf.jabref.bibtex.comparator.FieldComparator; -import net.sf.jabref.bibtex.comparator.FieldComparatorStack; +import net.sf.jabref.logic.bibtex.comparator.FieldComparator; +import net.sf.jabref.logic.bibtex.comparator.FieldComparatorStack; import net.sf.jabref.logic.layout.format.GetOpenOfficeType; import net.sf.jabref.logic.layout.format.RemoveBrackets; import net.sf.jabref.logic.layout.format.RemoveWhitespace; diff --git a/src/main/java/net/sf/jabref/exporter/SaveSession.java b/src/main/java/net/sf/jabref/exporter/SaveSession.java index ac0b5c1932d1..80deb6ee114b 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveSession.java +++ b/src/main/java/net/sf/jabref/exporter/SaveSession.java @@ -24,7 +24,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileBasedLock; @@ -48,8 +47,11 @@ * If committing fails, the temporary file will not be deleted. */ public class SaveSession { + private static final Log LOGGER = LogFactory.getLog(SaveSession.class); + // Filenames. + private static final String BACKUP_EXTENSION = ".bak"; public static final String LOCKFILE_SUFFIX = ".lock"; // The age in ms of a lockfile before JabRef will offer to "steal" the locked file: @@ -101,7 +103,7 @@ public void commit(File file) throws SaveException { if (file.exists() && backup) { String name = file.getName(); String path = file.getParent(); - File backupFile = new File(path, name + GUIGlobals.BACKUP_EXTENSION); + File backupFile = new File(path, name + BACKUP_EXTENSION); try { FileUtil.copyFile(file, backupFile, true); } catch (IOException ex) { diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index a2dc4119889a..7b628b740997 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -156,6 +156,9 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe private static final Log LOGGER = LogFactory.getLog(BasePanel.class); + // Divider size for BaseFrame split pane. 0 means non-resizable. + private static final int SPLIT_PANE_DIVIDER_SIZE = 4; + private final BibDatabase database; private final BibDatabaseContext bibDatabaseContext; private final MainTableDataModel tableModel; @@ -1484,7 +1487,7 @@ public void keyPressed(KeyEvent e) { public void setupMainPanel() { splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); - splitPane.setDividerSize(GUIGlobals.SPLIT_PANE_DIVIDER_SIZE); + splitPane.setDividerSize(SPLIT_PANE_DIVIDER_SIZE); // check whether a mainTable already existed and a floatSearch was active boolean floatSearchActive = (mainTable != null) && (this.tableModel.getSearchState() == MainTableDataModel.DisplayOption.FLOAT); @@ -2262,7 +2265,7 @@ public void newEntryShowing(BibEntry entry) { // Add the entry we are leaving to the history: if (showing != null) { previousEntries.add(showing); - if (previousEntries.size() > GUIGlobals.MAX_BACK_HISTORY_SIZE) { + if (previousEntries.size() > Globals.prefs.getInt(JabRefPreferences.MAX_BACK_HISTORY_SIZE)) { previousEntries.remove(0); } } diff --git a/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java b/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java index ca461e0493bd..33791ee18ed5 100644 --- a/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java @@ -47,7 +47,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.logic.l10n.Localization; @@ -56,6 +55,7 @@ import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.builder.ButtonBarBuilder; diff --git a/src/main/java/net/sf/jabref/gui/EntryMarker.java b/src/main/java/net/sf/jabref/gui/EntryMarker.java index f103f36edc3a..8435cd174f50 100644 --- a/src/main/java/net/sf/jabref/gui/EntryMarker.java +++ b/src/main/java/net/sf/jabref/gui/EntryMarker.java @@ -22,11 +22,11 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; public class EntryMarker { diff --git a/src/main/java/net/sf/jabref/gui/FieldContentSelector.java b/src/main/java/net/sf/jabref/gui/FieldContentSelector.java index d3d6b0ca46a4..5b012b841002 100644 --- a/src/main/java/net/sf/jabref/gui/FieldContentSelector.java +++ b/src/main/java/net/sf/jabref/gui/FieldContentSelector.java @@ -43,6 +43,7 @@ */ public class FieldContentSelector extends JComponent { + private static final int MAX_CONTENT_SELECTOR_WIDTH = 240; // The max width of the combobox for content selectors. private final JComboBox comboBox; private final FieldEditor editor; @@ -93,8 +94,8 @@ public FieldContentSelector(JabRefFrame frame, final BasePanel panel, @Override public Dimension getPreferredSize() { Dimension parents = super.getPreferredSize(); - if (parents.width > GUIGlobals.MAX_CONTENT_SELECTOR_WIDTH) { - parents.width = GUIGlobals.MAX_CONTENT_SELECTOR_WIDTH; + if (parents.width > MAX_CONTENT_SELECTOR_WIDTH) { + parents.width = MAX_CONTENT_SELECTOR_WIDTH; } return parents; } diff --git a/src/main/java/net/sf/jabref/gui/GUIGlobals.java b/src/main/java/net/sf/jabref/gui/GUIGlobals.java index 315808a81164..6b46f0f08383 100644 --- a/src/main/java/net/sf/jabref/gui/GUIGlobals.java +++ b/src/main/java/net/sf/jabref/gui/GUIGlobals.java @@ -43,62 +43,27 @@ * Static variables for graphics files and keyboard shortcuts. */ public class GUIGlobals { - private static final Log LOGGER = LogFactory.getLog(GUIGlobals.class); - // Frame titles. - public static final String FRAME_TITLE = "JabRef"; + private static final Log LOGGER = LogFactory.getLog(GUIGlobals.class); public static final String UNTITLED_TITLE = Localization.lang("untitled"); public static Font currentFont; - // Divider size for BaseFrame split pane. 0 means non-resizable. - public static final int SPLIT_PANE_DIVIDER_SIZE = 4; - public static final int SPLIT_PANE_DIVIDER_LOCATION = 160 + 15; // + 15 for possible scrollbar. - public static final int TABLE_ROW_PADDING = 9; - public static final int KEYBIND_COL_0 = 200; - public static final int KEYBIND_COL_1 = 80; // Added to the font size when determining table - public static final int MAX_CONTENT_SELECTOR_WIDTH = 240; // The max width of the combobox for content selectors. - - // Filenames. - public static final String BACKUP_EXTENSION = ".bak"; - private static final Map TABLE_ICONS = new HashMap<>(); // Contains table icon mappings. Set up - // further below. - public static final Color ACTIVE_EDITOR_COLOR = new Color(230, 230, 255); // Colors. public static final Color ENTRY_EDITOR_LABEL_COLOR = new Color(100, 100, 150); // Empty field, blue. - public static final Color NULL_FIELD_COLOR = new Color(75, 130, 95); // Valid field, green. - public static final Color ACTIVE_TABBED_COLOR = GUIGlobals.ENTRY_EDITOR_LABEL_COLOR.darker(); // active Database (JTabbedPane) - public static final Color INACTIVE_TABBED_COLOR = Color.black; // inactive Database + static final Color ACTIVE_TABBED_COLOR = ENTRY_EDITOR_LABEL_COLOR.darker(); // active Database (JTabbedPane) + static final Color INACTIVE_TABBED_COLOR = Color.black; // inactive Database public static Color editorTextColor; public static Color validFieldBackgroundColor; public static Color activeBackground; public static Color invalidFieldBackgroundColor; - - - public static final int MAX_BACK_HISTORY_SIZE = 10; // The maximum number of "Back" operations stored. - - // Constants controlling formatted bibtex output. - public static final int INDENT = 4; - public static final int LINE_LENGTH = 65; // Maximum - - public static final int NUMBER_COL_LENGTH = 32; - - public static final int WIDTH_ICON_COL_RANKING = 80; // Width of Ranking Icon Column + public static final Color NULL_FIELD_COLOR = new Color(75, 130, 95); // Valid field, green. + public static final Color ACTIVE_EDITOR_COLOR = new Color(230, 230, 255); public static final int WIDTH_ICON_COL = 26; - - // Column widths for export customization dialog table: - public static final int EXPORT_DIALOG_COL_0_WIDTH = 50; - public static final int EXPORT_DIALOG_COL_1_WIDTH = 200; - public static final int EXPORT_DIALOG_COL_2_WIDTH = 30; - - // Column widths for import customization dialog table: - public static final int IMPORT_DIALOG_COL_0_WIDTH = 200; - public static final int IMPORT_DIALOG_COL_1_WIDTH = 80; - public static final int IMPORT_DIALOG_COL_2_WIDTH = 200; - public static final int IMPORT_DIALOG_COL_3_WIDTH = 200; + public static final int WIDTH_ICON_COL_RANKING = 80; // Width of Ranking Icon Column static { // Set up entry editor colors, first time: diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index b4e1edfc2c78..3bf8c1084e13 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -70,9 +70,6 @@ import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; -import net.sf.jabref.bibtex.comparator.FieldComparator; import net.sf.jabref.external.DownloadExternalFile; import net.sf.jabref.external.ExternalFileMenuItem; import net.sf.jabref.gui.DuplicateResolverDialog.DuplicateResolverResult; @@ -90,6 +87,7 @@ import net.sf.jabref.gui.util.component.CheckBoxMessage; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.logic.bibtex.comparator.FieldComparator; import net.sf.jabref.logic.groups.AllEntriesGroup; import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.groups.GroupTreeNode; @@ -102,7 +100,9 @@ import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.model.entry.InternalBibtexFields; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index b6666c2519fd..4e6d0555a639 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -151,6 +151,9 @@ */ public class JabRefFrame extends JFrame implements OutputPrinter { + // Frame titles. + private static final String FRAME_TITLE = "JabRef"; + private static final Log LOGGER = LogFactory.getLog(JabRefFrame.class); private static final String ELLIPSES = "..."; @@ -578,7 +581,7 @@ private void init() { MyGlassPane glassPane = new MyGlassPane(); setGlassPane(glassPane); - setTitle(GUIGlobals.FRAME_TITLE); + setTitle(FRAME_TITLE); setIconImage(new ImageIcon(IconTheme.getIconUrl("jabrefIcon48")).getImage()); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @@ -668,7 +671,7 @@ public void setWindowTitle() { // no database open if (panel == null) { - setTitle(GUIGlobals.FRAME_TITLE); + setTitle(FRAME_TITLE); return; } @@ -677,10 +680,10 @@ public void setWindowTitle() { String changeFlag = panel.isModified() ? "*" : ""; if (panel.getBibDatabaseContext().getDatabaseFile() == null) { - setTitle(GUIGlobals.FRAME_TITLE + " - " + GUIGlobals.UNTITLED_TITLE + changeFlag + modeInfo); + setTitle(FRAME_TITLE + " - " + GUIGlobals.UNTITLED_TITLE + changeFlag + modeInfo); } else { String databaseFile = panel.getBibDatabaseContext().getDatabaseFile().getPath(); - setTitle(GUIGlobals.FRAME_TITLE + " - " + databaseFile + changeFlag + modeInfo); + setTitle(FRAME_TITLE + " - " + databaseFile + changeFlag + modeInfo); } } diff --git a/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java b/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java index 00c0f63f7828..383bd3daf1f6 100644 --- a/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java +++ b/src/main/java/net/sf/jabref/gui/SaveOrderConfigDisplay.java @@ -26,10 +26,10 @@ import javax.swing.JComboBox; import javax.swing.JPanel; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/SidePane.java b/src/main/java/net/sf/jabref/gui/SidePane.java index be8236a2c35e..4aee2acbeb35 100644 --- a/src/main/java/net/sf/jabref/gui/SidePane.java +++ b/src/main/java/net/sf/jabref/gui/SidePane.java @@ -33,7 +33,7 @@ */ public class SidePane extends JPanel { - private final Dimension PREFERRED_SIZE = new Dimension(GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION, 100); + private final Dimension PREFERRED_SIZE = new Dimension(175, 100); private final GridBagLayout gridBagLayout = new GridBagLayout(); diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index f9f9b07a9c71..beac57e5a8c2 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -47,8 +47,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.comparator.BibtexStringComparator; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFiles; @@ -57,6 +55,8 @@ import net.sf.jabref.gui.undo.UndoableRemoveString; import net.sf.jabref.gui.undo.UndoableStringChange; import net.sf.jabref.gui.util.PositionWindow; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.comparator.BibtexStringComparator; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.KeyCollisionException; diff --git a/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java b/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java index 740b0a1f8787..e156548f28ae 100644 --- a/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java +++ b/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java @@ -24,8 +24,8 @@ import javax.swing.JOptionPane; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.exporter.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java b/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java index 36d361f4e0bf..f1fcee95994f 100644 --- a/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java +++ b/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java @@ -41,12 +41,12 @@ import javax.swing.event.ListDataListener; import net.sf.jabref.MetaData; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 80f62ecca5d1..c8af85397290 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -66,11 +66,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.event.FieldChangedEvent; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.external.WriteXMPEntryEditorAction; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryContainer; @@ -101,6 +97,8 @@ import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.TypedBibEntry; import net.sf.jabref.logic.autocompleter.AutoCompleter; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.search.SearchQueryHighlightListener; @@ -111,6 +109,8 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryConverter; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.specialfields.SpecialFieldUpdateListener; import com.google.common.eventbus.Subscribe; @@ -128,6 +128,7 @@ * update themselves if the change is made from somewhere else. */ public class EntryEditor extends JPanel implements EntryContainer { + private static final Log LOGGER = LogFactory.getLog(EntryEditor.class); // A reference to the entry this object works on. @@ -540,7 +541,7 @@ private void setupSourcePanel() { source.setEditable(true); source.setLineWrap(true); - source.setTabSize(GUIGlobals.INDENT); + source.setTabSize(Globals.prefs.getInt(JabRefPreferences.INDENT)); source.addFocusListener(new FieldEditorFocusListener()); // Add the global focus listener, so a menu item can see if this field was focused when an action was called. source.addFocusListener(Globals.focusListener); @@ -1070,6 +1071,7 @@ public void actionPerformed(ActionEvent e) { } public class StoreFieldAction extends AbstractAction { + public StoreFieldAction() { super("Store field value"); putValue(Action.SHORT_DESCRIPTION, "Store field value"); diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java index b4ff29f84abf..f170f65968f5 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java @@ -40,8 +40,6 @@ import javax.swing.text.JTextComponent; import net.sf.jabref.Globals; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.autocompleter.AutoCompleteListener; @@ -53,6 +51,8 @@ import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.logic.autocompleter.AutoCompleter; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index f9304f2ae746..4148a8423a87 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -37,8 +37,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FieldContentSelector; import net.sf.jabref.gui.JabRefFrame; @@ -56,6 +54,8 @@ import net.sf.jabref.logic.util.date.EasyDateFormat; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; public class FieldExtraComponents { diff --git a/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingsDialog.java b/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingsDialog.java index ef4acdb98b48..3eeb6d793460 100644 --- a/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingsDialog.java +++ b/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingsDialog.java @@ -30,7 +30,6 @@ import javax.swing.table.TableColumnModel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.logic.l10n.Localization; /** @@ -39,6 +38,9 @@ @SuppressWarnings("serial") public class KeyBindingsDialog extends JDialog { + private static final int KEYBIND_COL_0 = 200; + private static final int KEYBIND_COL_1 = 80; // Added to the font size when determining table + private final JButton ok = new JButton(Localization.lang("OK")); private final JButton cancel = new JButton(Localization.lang("Cancel")); @@ -100,8 +102,8 @@ private void updateTableData() { // has to be done each time as the columnModel is dependent on the tableModel TableColumnModel cm = table.getColumnModel(); - cm.getColumn(0).setPreferredWidth(GUIGlobals.KEYBIND_COL_0); - cm.getColumn(1).setPreferredWidth(GUIGlobals.KEYBIND_COL_1); + cm.getColumn(0).setPreferredWidth(KEYBIND_COL_0); + cm.getColumn(1).setPreferredWidth(KEYBIND_COL_1); } private void activateListeners() { diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java index 5e7e556eb301..0fbdf9754a8e 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java @@ -40,8 +40,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexSingleField; -import net.sf.jabref.bibtex.comparator.FieldComparator; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryMarker; import net.sf.jabref.gui.GUIGlobals; @@ -56,8 +54,10 @@ import net.sf.jabref.gui.util.comparator.IconComparator; import net.sf.jabref.gui.util.comparator.RankingFieldComparator; import net.sf.jabref.logic.TypedBibEntry; +import net.sf.jabref.logic.bibtex.comparator.FieldComparator; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.BibtexSingleField; import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.specialfields.SpecialFieldsUtils; @@ -81,8 +81,6 @@ */ public class MainTable extends JTable { - - private static final Log LOGGER = LogFactory.getLog(MainTable.class); private final MainTableFormat tableFormat; diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java index 02d74068896a..69f906fd88fb 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java @@ -7,13 +7,14 @@ import javax.swing.JLabel; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; +import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; public class MainTableColumn { @@ -63,7 +64,7 @@ public String getDisplayName() { return null; } - StringJoiner joiner = new StringJoiner(MainTableFormat.COL_DEFINITION_FIELD_SEPARATOR); + StringJoiner joiner = new StringJoiner(Globals.COL_DEFINITION_FIELD_SEPARATOR); for (String field : bibtexFields) { joiner.add(field); } diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java index 31917d384126..fb18c38ba196 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java @@ -35,10 +35,6 @@ * Class defining the contents and column headers of the main table. */ public class MainTableFormat implements TableFormat { - // Character separating field names that are to be used in sequence as - // fallbacks for a single column (e.g. "author/editor" to use editor where - // author is not set): - public static final String COL_DEFINITION_FIELD_SEPARATOR = "/"; // Values to gather iconImages for those columns // These values are also used to put a heading into the table; see getColumnName(int) @@ -140,7 +136,7 @@ public void updateTableFormat() { // stored column name will be used as columnName // There might be more than one field to display, e.g., "author/editor" or "date/year" - so split // at MainTableFormat.COL_DEFINITION_FIELD_SEPARATOR - String[] fields = columnName.split(MainTableFormat.COL_DEFINITION_FIELD_SEPARATOR); + String[] fields = columnName.split(Globals.COL_DEFINITION_FIELD_SEPARATOR); tableColumns.add(new MainTableColumn(columnName, Arrays.asList(fields), database)); } diff --git a/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java b/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java index b45b936fa0f2..53dc68764168 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java @@ -25,7 +25,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.InternalBibtexFields; +import net.sf.jabref.model.entry.InternalBibtexFields; /** * Listens for TableColumnModelEvents to keep track of changes made to the diff --git a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java index 614ca0000521..727c4718d661 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java +++ b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java @@ -7,12 +7,12 @@ import javax.swing.JLabel; import net.sf.jabref.Globals; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; diff --git a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java index 4ab35bbcd4af..3f07fd161ce9 100644 --- a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java @@ -29,7 +29,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryMarker; import net.sf.jabref.gui.FileListTableModel; @@ -40,6 +39,7 @@ import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java index 16266ff08147..0cea3f813a9d 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java @@ -45,9 +45,9 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.gui.PreviewPanel; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.formatter.casechanger.SentenceCaseFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseMode; diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java index aa4295ec000b..827a74e55407 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java @@ -46,8 +46,8 @@ import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; -import net.sf.jabref.bibtex.comparator.FieldComparator; -import net.sf.jabref.bibtex.comparator.FieldComparatorStack; +import net.sf.jabref.logic.bibtex.comparator.FieldComparator; +import net.sf.jabref.logic.bibtex.comparator.FieldComparatorStack; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.openoffice.OOBibStyle; diff --git a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java index 8114f2628d44..72bba9bd312d 100644 --- a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java +++ b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java @@ -111,10 +111,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.gui.ClipBoardManager; import net.sf.jabref.gui.EntryMarker; import net.sf.jabref.gui.FileDialogs; @@ -125,11 +121,15 @@ import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.util.component.OverlayPanel; import net.sf.jabref.importer.fileformat.FreeCiteImporter; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.UpdateField; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java index 876a7e1409dd..c6ba1c5b77c7 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java @@ -46,8 +46,6 @@ import javax.swing.table.TableModel; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexSingleField; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.gui.BasePanel; @@ -57,6 +55,8 @@ import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFiles; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.BibtexSingleField; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.specialfields.SpecialFieldsUtils; import com.jgoodies.forms.builder.DefaultFormBuilder; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java index 483fa2b46fb8..6aed10a300a5 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java @@ -32,9 +32,9 @@ import javax.swing.JTextField; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java index 950eb935fe89..6a26648ab682 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java @@ -48,10 +48,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; -import net.sf.jabref.bibtex.comparator.EntryComparator; -import net.sf.jabref.bibtex.comparator.FieldComparator; import net.sf.jabref.external.ExternalFileMenuItem; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileListEntry; @@ -66,9 +62,13 @@ import net.sf.jabref.gui.maintable.MainTableNameFormatter; import net.sf.jabref.gui.renderer.GeneralRenderer; import net.sf.jabref.gui.util.comparator.IconComparator; +import net.sf.jabref.logic.bibtex.comparator.EntryComparator; +import net.sf.jabref.logic.bibtex.comparator.FieldComparator; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; diff --git a/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java b/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java index 96f1a56b9e69..76cd03428cd2 100644 --- a/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java +++ b/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java @@ -25,11 +25,11 @@ import java.util.List; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.desktop.JabRefDesktop; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java index eb6c56c47849..aa0fe301dd82 100644 --- a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java @@ -44,7 +44,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FileDialogs; -import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFiles; @@ -62,14 +61,19 @@ */ public class ImportCustomizationDialog extends JDialog { + // Column widths for import customization dialog table: + private static final int COL_0_WIDTH = 200; + private static final int COL_1_WIDTH = 80; + private static final int COL_2_WIDTH = 200; + private static final int COL_3_WIDTH = 200; + private final JTable customImporterTable; private static final Log LOGGER = LogFactory.getLog(ImportCustomizationDialog.class); /** * - * @param frame_ - * @throws HeadlessException + * @param frame */ public ImportCustomizationDialog(final JabRefFrame frame) { super(frame, Localization.lang("Manage custom imports"), false); @@ -77,10 +81,10 @@ public ImportCustomizationDialog(final JabRefFrame frame) { ImportTableModel tableModel = new ImportTableModel(); customImporterTable = new JTable(tableModel); TableColumnModel cm = customImporterTable.getColumnModel(); - cm.getColumn(0).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_0_WIDTH); - cm.getColumn(1).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_1_WIDTH); - cm.getColumn(2).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_2_WIDTH); - cm.getColumn(3).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_3_WIDTH); + cm.getColumn(0).setPreferredWidth(COL_0_WIDTH); + cm.getColumn(1).setPreferredWidth(COL_1_WIDTH); + cm.getColumn(2).setPreferredWidth(COL_2_WIDTH); + cm.getColumn(3).setPreferredWidth(COL_3_WIDTH); JScrollPane sp = new JScrollPane(customImporterTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); customImporterTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -227,8 +231,8 @@ public void actionPerformed(ActionEvent e) { */ @Override public Dimension getSize() { - int width = GUIGlobals.IMPORT_DIALOG_COL_0_WIDTH + GUIGlobals.IMPORT_DIALOG_COL_1_WIDTH - + GUIGlobals.IMPORT_DIALOG_COL_2_WIDTH + GUIGlobals.IMPORT_DIALOG_COL_3_WIDTH; + int width = COL_0_WIDTH + COL_1_WIDTH + + COL_2_WIDTH + COL_3_WIDTH; return new Dimension(width, width / 2); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 41adec5e061c..7369c9020ea0 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -29,10 +29,9 @@ import java.util.Objects; import net.sf.jabref.MetaData; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.CustomEntryTypesManager; +import net.sf.jabref.logic.bibtex.FieldContentParser; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.KeyCollisionException; @@ -40,7 +39,9 @@ import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.model.entry.InternalBibtexFields; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java index 3690c65d43e2..11adb88f8465 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java @@ -18,8 +18,8 @@ import java.util.Arrays; import java.util.Objects; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; /** * Returns an autocompleter to a given fieldname. diff --git a/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java similarity index 98% rename from src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java rename to src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java index 5e4cf86f5586..629c8c1d32b2 100644 --- a/src/main/java/net/sf/jabref/bibtex/BibEntryWriter.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bibtex; +package net.sf.jabref.logic.bibtex; import java.io.IOException; import java.io.Writer; @@ -10,16 +10,17 @@ import java.util.function.Predicate; import net.sf.jabref.Globals; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.logic.TypedBibEntry; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.google.common.base.Strings; + public class BibEntryWriter { private final LatexFieldFormatter fieldFormatter; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FieldContentParser.java b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java similarity index 92% rename from src/main/java/net/sf/jabref/importer/fileformat/FieldContentParser.java rename to src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java index ed522086cf63..825315e1c2f6 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FieldContentParser.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2011 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -13,7 +13,7 @@ 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.importer.fileformat; +package net.sf.jabref.logic.bibtex; import java.util.HashSet; import java.util.List; @@ -36,7 +36,7 @@ public class FieldContentParser { public FieldContentParser() { multiLineFields = new HashSet<>(); - // the following two are also coded in net.sf.jabref.exporter.LatexFieldFormatter.format(String, String) + // the following two are also coded in net.sf.jabref.logic.bibtex.LatexFieldFormatter.format(String, String) multiLineFields.add("abstract"); multiLineFields.add("review"); // the file field should not be formatted, therefore we treat it as a multi line field diff --git a/src/main/java/net/sf/jabref/exporter/LatexFieldFormatter.java b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java similarity index 97% rename from src/main/java/net/sf/jabref/exporter/LatexFieldFormatter.java rename to src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java index be556ab1e343..a93df48ac424 100644 --- a/src/main/java/net/sf/jabref/exporter/LatexFieldFormatter.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java @@ -13,17 +13,15 @@ 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.exporter; +package net.sf.jabref.logic.bibtex; import java.util.ArrayList; import java.util.List; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.InternalBibtexFields; -import net.sf.jabref.gui.GUIGlobals; -import net.sf.jabref.importer.fileformat.FieldContentParser; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.entry.InternalBibtexFields; /** * Currently the only implementation of net.sf.jabref.exporter.FieldFormatter @@ -38,7 +36,6 @@ public class LatexFieldFormatter { // "Fieldname" to indicate that a field should be treated as a bibtex string. Used when writing database to file. public static final String BIBTEX_STRING = "__string"; - private StringBuilder stringBuilder; private final boolean neverFailOnHashes; @@ -47,6 +44,7 @@ public class LatexFieldFormatter { private final char valueDelimiterStartOfValue; private final char valueDelimiterEndOfValue; private final List doNotResolveStringsFors; + private final int lineLength; private final FieldContentParser parser; @@ -62,6 +60,7 @@ private LatexFieldFormatter(boolean neverFailOnHashes) { valueDelimiterStartOfValue = Globals.prefs.getValueDelimiters(0); valueDelimiterEndOfValue = Globals.prefs.getValueDelimiters(1); doNotResolveStringsFors = Globals.prefs.getStringList(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR); + lineLength = Globals.prefs.getInt(JabRefPreferences.LINE_LENGTH); parser = new FieldContentParser(); } @@ -273,7 +272,7 @@ private void writeStringLabel(String text, int startPos, int endPos, } private void putIn(String s) { - stringBuilder.append(StringUtil.wrap(s, GUIGlobals.LINE_LENGTH)); + stringBuilder.append(StringUtil.wrap(s, lineLength)); } private static void checkBraces(String text) throws IllegalArgumentException { diff --git a/src/main/java/net/sf/jabref/bibtex/comparator/BibtexStringComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/BibtexStringComparator.java similarity index 98% rename from src/main/java/net/sf/jabref/bibtex/comparator/BibtexStringComparator.java rename to src/main/java/net/sf/jabref/logic/bibtex/comparator/BibtexStringComparator.java index ce26c053cb58..47ac0775f71e 100644 --- a/src/main/java/net/sf/jabref/bibtex/comparator/BibtexStringComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/BibtexStringComparator.java @@ -13,7 +13,7 @@ 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.bibtex.comparator; +package net.sf.jabref.logic.bibtex.comparator; import java.util.Comparator; diff --git a/src/main/java/net/sf/jabref/bibtex/comparator/CrossRefEntryComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/CrossRefEntryComparator.java similarity index 97% rename from src/main/java/net/sf/jabref/bibtex/comparator/CrossRefEntryComparator.java rename to src/main/java/net/sf/jabref/logic/bibtex/comparator/CrossRefEntryComparator.java index c504da4edb9c..bc7ecb4c35b3 100644 --- a/src/main/java/net/sf/jabref/bibtex/comparator/CrossRefEntryComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/CrossRefEntryComparator.java @@ -13,7 +13,7 @@ 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.bibtex.comparator; +package net.sf.jabref.logic.bibtex.comparator; import java.util.Comparator; diff --git a/src/main/java/net/sf/jabref/bibtex/comparator/EntryComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/EntryComparator.java similarity index 97% rename from src/main/java/net/sf/jabref/bibtex/comparator/EntryComparator.java rename to src/main/java/net/sf/jabref/logic/bibtex/comparator/EntryComparator.java index 7e272668d929..8a8f25b34e1a 100644 --- a/src/main/java/net/sf/jabref/bibtex/comparator/EntryComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/EntryComparator.java @@ -13,15 +13,15 @@ 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.bibtex.comparator; +package net.sf.jabref.logic.bibtex.comparator; import java.util.Comparator; import java.util.Objects; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; /** * This implementation of Comparator takes care of most of the details of sorting BibTeX entries in JabRef. It is diff --git a/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java similarity index 95% rename from src/main/java/net/sf/jabref/bibtex/comparator/FieldComparator.java rename to src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java index ade5f192e0f2..8d5357a282e6 100644 --- a/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java @@ -13,7 +13,7 @@ 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.bibtex.comparator; +package net.sf.jabref.logic.bibtex.comparator; import java.text.Collator; import java.text.ParseException; @@ -22,13 +22,13 @@ import java.util.Locale; import java.util.Objects; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; -import net.sf.jabref.gui.maintable.MainTableFormat; +import net.sf.jabref.Globals; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; /** @@ -72,7 +72,7 @@ public FieldComparator(String field) { public FieldComparator(String field, boolean reversed) { this.fieldName = Objects.requireNonNull(field); - this.field = fieldName.split(MainTableFormat.COL_DEFINITION_FIELD_SEPARATOR); + this.field = fieldName.split(Globals.COL_DEFINITION_FIELD_SEPARATOR); fieldType = determineFieldType(); isNumeric = InternalBibtexFields.isNumeric(this.field[0]); diff --git a/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparatorStack.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparatorStack.java similarity index 97% rename from src/main/java/net/sf/jabref/bibtex/comparator/FieldComparatorStack.java rename to src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparatorStack.java index 7c77c4a9c2f8..6696cedd564a 100644 --- a/src/main/java/net/sf/jabref/bibtex/comparator/FieldComparatorStack.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparatorStack.java @@ -13,7 +13,7 @@ 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.bibtex.comparator; +package net.sf.jabref.logic.bibtex.comparator; import java.util.Comparator; import java.util.List; diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 0a93ac463600..10c6f5c4f5ad 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -15,12 +15,12 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.FileField; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.ParsedFileField; public class IntegrityCheck { diff --git a/src/main/java/net/sf/jabref/logic/util/UpdateField.java b/src/main/java/net/sf/jabref/logic/util/UpdateField.java index 7c053221e8a0..691842707d02 100644 --- a/src/main/java/net/sf/jabref/logic/util/UpdateField.java +++ b/src/main/java/net/sf/jabref/logic/util/UpdateField.java @@ -5,10 +5,10 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.util.date.EasyDateFormat; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; public class UpdateField { diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java index 04a0b3447c7e..4219dc0bb871 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java @@ -25,13 +25,13 @@ import java.util.TreeSet; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.model.entry.InternalBibtexFields; import org.apache.jempbox.xmp.XMPMetadata; import org.apache.jempbox.xmp.XMPSchema; diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index a3c1183c5322..1a4d690e0202 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -43,11 +43,11 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.TypedBibEntry; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.Author; diff --git a/src/main/java/net/sf/jabref/model/DuplicateCheck.java b/src/main/java/net/sf/jabref/model/DuplicateCheck.java index 3e6eb2bd93f1..a00fd0660ea2 100644 --- a/src/main/java/net/sf/jabref/model/DuplicateCheck.java +++ b/src/main/java/net/sf/jabref/model/DuplicateCheck.java @@ -21,13 +21,13 @@ import java.util.Optional; import java.util.Set; -import net.sf.jabref.bibtex.FieldProperties; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldProperties; +import net.sf.jabref.model.entry.InternalBibtexFields; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/bibtex/BibtexSingleField.java b/src/main/java/net/sf/jabref/model/entry/BibtexSingleField.java similarity index 99% rename from src/main/java/net/sf/jabref/bibtex/BibtexSingleField.java rename to src/main/java/net/sf/jabref/model/entry/BibtexSingleField.java index 82374f140cc9..0b2986388c2b 100644 --- a/src/main/java/net/sf/jabref/bibtex/BibtexSingleField.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexSingleField.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bibtex; +package net.sf.jabref.model.entry; import java.util.EnumSet; import java.util.Set; diff --git a/src/main/java/net/sf/jabref/bibtex/FieldProperties.java b/src/main/java/net/sf/jabref/model/entry/FieldProperties.java similarity index 92% rename from src/main/java/net/sf/jabref/bibtex/FieldProperties.java rename to src/main/java/net/sf/jabref/model/entry/FieldProperties.java index d4a9f7dafb67..1e1d190a8b63 100644 --- a/src/main/java/net/sf/jabref/bibtex/FieldProperties.java +++ b/src/main/java/net/sf/jabref/model/entry/FieldProperties.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bibtex; +package net.sf.jabref.model.entry; import java.util.EnumSet; import java.util.Set; diff --git a/src/main/java/net/sf/jabref/bibtex/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java similarity index 99% rename from src/main/java/net/sf/jabref/bibtex/InternalBibtexFields.java rename to src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index 83d2c8125c32..44708f03482a 100644 --- a/src/main/java/net/sf/jabref/bibtex/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -28,7 +28,7 @@ // modified : r.nagel 25.04.2006 // export/import of some definition from/to a xml file -package net.sf.jabref.bibtex; +package net.sf.jabref.model.entry; import java.util.ArrayList; import java.util.Arrays; @@ -44,7 +44,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.specialfields.SpecialFieldsUtils; public class InternalBibtexFields { diff --git a/src/main/java/net/sf/jabref/sql/SQLUtil.java b/src/main/java/net/sf/jabref/sql/SQLUtil.java index efbeb12995b6..78e86de4489e 100644 --- a/src/main/java/net/sf/jabref/sql/SQLUtil.java +++ b/src/main/java/net/sf/jabref/sql/SQLUtil.java @@ -24,7 +24,7 @@ import java.util.Collections; import java.util.List; -import net.sf.jabref.bibtex.InternalBibtexFields; +import net.sf.jabref.model.entry.InternalBibtexFields; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/util/Util.java b/src/main/java/net/sf/jabref/util/Util.java index ab254038b7b2..6e2478be077c 100644 --- a/src/main/java/net/sf/jabref/util/Util.java +++ b/src/main/java/net/sf/jabref/util/Util.java @@ -27,13 +27,13 @@ import javax.swing.JOptionPane; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.gui.worker.AbstractWorker; import net.sf.jabref.gui.worker.CallBack; import net.sf.jabref.gui.worker.Worker; import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.KeywordGroup; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.InternalBibtexFields; /** * utility functions diff --git a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java index 92c769fdd515..df2f79f5023c 100644 --- a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java @@ -254,21 +254,25 @@ public void writeStringAndEncoding() throws IOException { @Test public void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws IOException { - EntryTypes.addOrModifyCustomEntryType(new CustomEntryType("customizedType", "required", "optional")); - BibEntry entry = new BibEntry(); - entry.setType("customizedType"); - database.insertEntry(entry); - - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.singletonList(entry), - new SavePreferences()); - - assertEquals( - Globals.NEWLINE + - "@Customizedtype{," + Globals.NEWLINE + "}" + Globals.NEWLINE + Globals.NEWLINE - + "@Comment{jabref-meta: databaseType:bibtex;}" - + Globals.NEWLINE + Globals.NEWLINE - + "@Comment{jabref-entrytype: Customizedtype: req[required] opt[optional]}" + Globals.NEWLINE, - stringWriter.toString()); + try { + EntryTypes.addOrModifyCustomEntryType(new CustomEntryType("customizedType", "required", "optional")); + BibEntry entry = new BibEntry(); + entry.setType("customizedType"); + database.insertEntry(entry); + + databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.singletonList(entry), + new SavePreferences()); + + assertEquals( + Globals.NEWLINE + + "@Customizedtype{," + Globals.NEWLINE + "}" + Globals.NEWLINE + Globals.NEWLINE + + "@Comment{jabref-meta: databaseType:bibtex;}" + + Globals.NEWLINE + Globals.NEWLINE + + "@Comment{jabref-entrytype: Customizedtype: req[required] opt[optional]}" + Globals.NEWLINE, + stringWriter.toString()); + } finally { + EntryTypes.removeAllCustomEntryTypes(); + } } @Test diff --git a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java index 76bc5e1af901..da12344752a9 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java @@ -10,7 +10,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java index 6346b21b0367..16ab0971ac60 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java @@ -15,8 +15,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java index 20ff3a2c3b61..43d662aab35b 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java @@ -8,8 +8,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java index c9fe85fe19a3..0ef18788af1f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java @@ -13,7 +13,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index 63a876b0e0a4..8aee52bb74ba 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -9,8 +9,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index 3fa81ac21c6b..7e8718953db8 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -10,8 +10,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java index ed6af8895b58..c47bf4390bbc 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java @@ -8,8 +8,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index 3857bf8db4db..81a442e9901a 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -8,8 +8,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java index 69b3227f1ec3..f3b6a0d3fc16 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java @@ -8,7 +8,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java index 6128f1457ad3..5b6ab5d02e71 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java @@ -8,8 +8,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index f4dd226bf957..4b113c79bfb1 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -7,8 +7,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java index e86c461ccf53..e452ca8c6498 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java @@ -7,8 +7,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryAssert; import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/bibtex/BibEntryAssert.java b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryAssert.java similarity index 99% rename from src/test/java/net/sf/jabref/bibtex/BibEntryAssert.java rename to src/test/java/net/sf/jabref/logic/bibtex/BibEntryAssert.java index 2db43de19cc1..e68e68d92524 100644 --- a/src/test/java/net/sf/jabref/bibtex/BibEntryAssert.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryAssert.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bibtex; +package net.sf.jabref.logic.bibtex; import java.io.IOException; import java.io.InputStream; diff --git a/src/test/java/net/sf/jabref/bibtex/BibEntryWriterTest.java b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java similarity index 99% rename from src/test/java/net/sf/jabref/bibtex/BibEntryWriterTest.java rename to src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java index eaef55540c72..3721ae7650ea 100644 --- a/src/test/java/net/sf/jabref/bibtex/BibEntryWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bibtex; +package net.sf.jabref.logic.bibtex; import java.io.IOException; import java.io.StringReader; @@ -8,7 +8,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabaseMode; diff --git a/src/test/java/net/sf/jabref/bibtex/EntryTypesTestBibLatex.java b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java similarity index 97% rename from src/test/java/net/sf/jabref/bibtex/EntryTypesTestBibLatex.java rename to src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java index 29bc224496c8..63f6c8bdd7f9 100644 --- a/src/test/java/net/sf/jabref/bibtex/EntryTypesTestBibLatex.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bibtex; +package net.sf.jabref.logic.bibtex; import java.util.Optional; diff --git a/src/test/java/net/sf/jabref/bibtex/EntryTypesTestBibtex.java b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java similarity index 88% rename from src/test/java/net/sf/jabref/bibtex/EntryTypesTestBibtex.java rename to src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java index 539cf04a1c8a..c12c6e0f675e 100644 --- a/src/test/java/net/sf/jabref/bibtex/EntryTypesTestBibtex.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java @@ -1,7 +1,8 @@ -package net.sf.jabref.bibtex; +package net.sf.jabref.logic.bibtex; import java.util.ArrayList; import java.util.Optional; +import java.util.stream.Collectors; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; @@ -40,7 +41,8 @@ public void testBibtexMode() { assertEquals(BibtexEntryTypes.ARTICLE, EntryTypes.getType("article", BibDatabaseMode.BIBTEX).get()); assertEquals(Optional.empty(), EntryTypes.getType("aaaaarticle", BibDatabaseMode.BIBTEX)); assertEquals(Optional.empty(), EntryTypes.getStandardType("aaaaarticle", BibDatabaseMode.BIBTEX)); - assertEquals(19, EntryTypes.getAllValues(BibDatabaseMode.BIBTEX).size()); + + assertEquals("Values: " + EntryTypes.getAllValues(BibDatabaseMode.BIBTEX).stream().map(entryType -> entryType.getName()).collect(Collectors.toList()), 19, EntryTypes.getAllValues(BibDatabaseMode.BIBTEX).size()); assertEquals(19, EntryTypes.getAllTypes(BibDatabaseMode.BIBTEX).size()); // Edit the "article" entry type diff --git a/src/test/java/net/sf/jabref/importer/fileformat/FieldContentParserTest.java b/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java similarity index 97% rename from src/test/java/net/sf/jabref/importer/fileformat/FieldContentParserTest.java rename to src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java index c93ac455ac08..40d076aafb05 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/FieldContentParserTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.importer.fileformat; +package net.sf.jabref.logic.bibtex; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; diff --git a/src/test/java/net/sf/jabref/exporter/LatexFieldFormatterTests.java b/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java similarity index 97% rename from src/test/java/net/sf/jabref/exporter/LatexFieldFormatterTests.java rename to src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java index 6414280e2a83..24e914c50629 100644 --- a/src/test/java/net/sf/jabref/exporter/LatexFieldFormatterTests.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.bibtex; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; @@ -9,9 +9,6 @@ import static org.junit.Assert.assertEquals; -/** - * Created by joerg on 05.10.2015. - */ public class LatexFieldFormatterTests { private LatexFieldFormatter formatter; diff --git a/src/test/java/net/sf/jabref/bibtex/comparator/BibtexStringComparatorTest.java b/src/test/java/net/sf/jabref/logic/bibtex/comparator/BibtexStringComparatorTest.java similarity index 97% rename from src/test/java/net/sf/jabref/bibtex/comparator/BibtexStringComparatorTest.java rename to src/test/java/net/sf/jabref/logic/bibtex/comparator/BibtexStringComparatorTest.java index 45ec3bfb83a9..ab4bfa84f4b2 100644 --- a/src/test/java/net/sf/jabref/bibtex/comparator/BibtexStringComparatorTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/comparator/BibtexStringComparatorTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bibtex.comparator; +package net.sf.jabref.logic.bibtex.comparator; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.IdGenerator; diff --git a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java index 5fe5142939ef..f21cd2ce41cb 100644 --- a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java @@ -12,10 +12,10 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.bibtex.InternalBibtexFields; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import org.junit.Before; import org.junit.Rule; diff --git a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java index 994d763a77e2..ec91879e7670 100644 --- a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java @@ -28,10 +28,10 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibEntryWriter; -import net.sf.jabref.exporter.LatexFieldFormatter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/test/java/net/sf/jabref/model/entry/IEEETranEntryTypesTest.java b/src/test/java/net/sf/jabref/model/entry/IEEETranEntryTypesTest.java index 9c57d005f2b0..c7c196f011f6 100644 --- a/src/test/java/net/sf/jabref/model/entry/IEEETranEntryTypesTest.java +++ b/src/test/java/net/sf/jabref/model/entry/IEEETranEntryTypesTest.java @@ -2,8 +2,6 @@ import java.util.List; -import net.sf.jabref.bibtex.InternalBibtexFields; - import org.junit.Assert; import org.junit.Test; From b8abc2f9f880182819b872e85a1b13df8053f7af Mon Sep 17 00:00:00 2001 From: MLEP Date: Mon, 23 May 2016 11:59:49 +0200 Subject: [PATCH 088/268] French localization: translation of the 4 empty strings (#1433) * French localization: translation of the 2 empty strings * French localization: translation of the 2 other empty strings --- src/main/resources/l10n/JabRef_fr.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 3ff6a2635295..161780ace8c4 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -391,7 +391,7 @@ Invalid_date_format=Format_de_date_invalide Invalid_URL=URL_invalide Inverted=Complémentaire ISO_abbreviation=Abréviation_ISO -Online_help= +Online_help=Aide_en_ligne JabRef_preferences=Préférences_pour_JabRef Journal_abbreviations=Abréviations_de_journaux Journal_list_preview=Prévisualisation_de_la_liste_des_journaux @@ -410,7 +410,7 @@ Last_modified=Dernier_modifié LaTeX_AUX_file=Fichier_LaTeX_AUX Leave_file_in_its_current_directory=Laisser_le_fichier_dans_son_répertoire_courant Left=Gauche -Level= +Level=Niveau Limit_to_fields=Restreindre_aux_champs Limit_to_selected_entries=Restreindre_aux_seules_entrées_sélectionnées Link=Lien @@ -1628,6 +1628,6 @@ booktitle_ends_with_'conference_on'=le_titre_d'ouvrage_se_termine_par_'conferenc BibTeX_key=Clef_BibTeX Message=Message -Get_fulltext= +Get_fulltext=Obtenir_le_document -Download_from_URL= +Download_from_URL=Télécharger_depuis_l'URL From 4f870e79358a4e4876b365f5bbb1cb2c0cff66a2 Mon Sep 17 00:00:00 2001 From: bruehldev Date: Mon, 23 May 2016 13:40:40 +0200 Subject: [PATCH 089/268] MedlineImporterTest (#547) * add MedlineImporterTest and a bugfix for StringUtil --- .../jabref/logic/util/strings/StringUtil.java | 46 ++++ .../fileformat/MedlineImporterTest.java | 100 ++++++++ .../fileformat/MedlineImporterTestFiles.java | 79 ++++++ .../MedlineImporterTestArticleID.bib | 14 ++ .../MedlineImporterTestArticleID.xml | 230 ++++++++++++++++++ .../MedlineImporterTestMalformedEntry.xml | 4 + .../MedlineImporterTestMinimalEntry.bib | 4 + .../MedlineImporterTestMinimalEntry.xml | 4 + .../MedlineImporterTestSingleEntry.bib | 15 ++ .../MedlineImporterTestSingleEntry.xml | 143 +++++++++++ 10 files changed, 639 insertions(+) create mode 100644 src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java create mode 100644 src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMalformedEntry.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml diff --git a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java index 86a6e3bdf6cb..12ff8c21e8aa 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java @@ -23,6 +23,7 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; +import net.sf.jabref.model.entry.Author; import com.google.common.base.CharMatcher; @@ -625,6 +626,51 @@ public static String replaceSpecialCharacters(String s) { return result; } + /** + * Expand initials, e.g. EH Wissler -> E. H. Wissler or Wissler, EH -> Wissler, E. H. + * + * @param name + * @return The name after expanding initials. + */ + public static String expandAuthorInitials(String name) { + String[] authors = name.split(" and "); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < authors.length; i++) { + if (authors[i].contains(", ")) { + String[] names = authors[i].split(", "); + if (names.length > 0) { + sb.append(names[0]); + if (names.length > 1) { + sb.append(", "); + } + } + for (int j = 1; j < names.length; j++) { + if (j == 1) { + sb.append(Author.addDotIfAbbreviation(names[j])); + } else { + sb.append(names[j]); + } + if (j < (names.length - 1)) { + sb.append(", "); + } + } + } else { + String[] names = authors[i].split(" "); + if (names.length > 0) { + sb.append(Author.addDotIfAbbreviation(names[0])); + } + for (int j = 1; j < names.length; j++) { + sb.append(' '); + sb.append(names[j]); + } + } + if (i < (authors.length - 1)) { + sb.append(" and "); + } + } + return sb.toString().trim(); + } + /** * Return a String with n spaces * diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java new file mode 100644 index 000000000000..5a16d5c1f1be --- /dev/null +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java @@ -0,0 +1,100 @@ +package net.sf.jabref.importer.fileformat; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.model.entry.BibEntry; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.junit.Assert.assertEquals; + +/** + * Articles in the medline format can be downloaded from http://www.ncbi.nlm.nih.gov/pubmed/. + * 1. Search for a term and make sure you have selected the PubMed database + * 2. Select the results you want to export by checking their checkboxes + * 3. Press on the 'Send to' drop down menu on top of the search results + * 4. Select 'File' as Destination and 'XML' as Format + * 5. Press 'Create File' to download your search results in a medline xml file + * + * @author Daniel Mair/Bruehl + * + */ +@RunWith(MockitoJUnitRunner.class) +public class MedlineImporterTest { + + private MedlineImporter medlineImporter; + private static final String FILEFORMAT_PATH = "src/test/resources/net/sf/jabref/importer/fileformat"; + + /** + * Generates a List of all files in the package "/src/test/resources/net/sf/jabref/importer/fileformat" + * @return A list of Names + * @throws IOException + */ + public List getTestFiles() throws IOException { + List files = new ArrayList<>(); + try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(FILEFORMAT_PATH))) { + stream.forEach(n -> files.add(n.getFileName().toString())); + } + return files; + } + + @Before + public void setUp() throws Exception { + Globals.prefs = JabRefPreferences.getInstance(); + this.medlineImporter = new MedlineImporter(); + } + + @Test + public void testExceptionOnInputStream() throws IOException { + try (InputStream is = Mockito.mock(InputStream.class)) { + Mockito.doThrow(new IOException()).when(is).read(); + List entry = medlineImporter.importEntries(is, new OutputPrinterToNull()); + Assert.assertTrue(entry.isEmpty()); + } + } + + @Test + public void testGetItemsEmpty() { + MedlineHandler handler = new MedlineHandler(); + assertEquals(Collections.emptyList(), handler.getItems()); + } + + @Test + public void testGetFormatName() { + assertEquals("Medline", medlineImporter.getFormatName()); + } + + @Test + public void testGetCLIId() { + assertEquals("medline", medlineImporter.getCLIId()); + } + + @Test + public void testIsRecognizedFormatReject() throws IOException { + List list = getTestFiles().stream().filter(n -> !n.startsWith("MedlineImporter")) + .collect(Collectors.toList()); + + for (String str : list) { + try (InputStream is = MedlineImporter.class.getResourceAsStream(str)) { + Assert.assertFalse(medlineImporter.isRecognizedFormat(is)); + } + } + } +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java new file mode 100644 index 000000000000..333bbb6330b1 --- /dev/null +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java @@ -0,0 +1,79 @@ +package net.sf.jabref.importer.fileformat; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.importer.OutputPrinterToNull; +import net.sf.jabref.logic.bibtex.BibEntryAssert; +import net.sf.jabref.model.entry.BibEntry; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class MedlineImporterTestFiles { + + private final static String FILEFORMAT_PATH = "src/test/resources/net/sf/jabref/importer/fileformat"; + + private MedlineImporter medlineImporter; + + @Parameter + public String fileName; + + + @Before + public void setUp() { + Globals.prefs = JabRefPreferences.getInstance(); + medlineImporter = new MedlineImporter(); + } + + @Parameters(name = "{0}") + public static Collection fileNames() throws IOException { + List files = new ArrayList<>(); + try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(FILEFORMAT_PATH))) { + stream.forEach(n -> files.add(n.getFileName().toString())); + } + return files.stream().filter(n -> n.startsWith("MedlineImporterTest")).filter(n -> n.endsWith(".xml")) + .collect(Collectors.toList()); + } + + @Test + public void testIsRecognizedFormat() throws IOException { + try (InputStream stream = MedlineImporterTest.class.getResourceAsStream(fileName)) { + Assert.assertTrue(medlineImporter.isRecognizedFormat(stream)); + } + } + + @Test + @Ignore + public void testImportEntries() throws IOException { + try (InputStream inputStream = MedlineImporterTest.class.getResourceAsStream(fileName)) { + List medlineEntries = medlineImporter.importEntries(inputStream, new OutputPrinterToNull()); + String bibFileName = fileName.replace(".xml", ".bib"); + if (medlineEntries.isEmpty()) { + assertEquals(Collections.emptyList(), medlineEntries); + } else { + BibEntryAssert.assertEquals(MedlineImporterTest.class, bibFileName, medlineEntries); + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib new file mode 100644 index 000000000000..d0414750291d --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib @@ -0,0 +1,14 @@ +% Encoding: UTF-8 + +@article{, + abstract = {This abstract is a dummy.}, + author = {Rhein, Joshua and Bahr, Nathan C. and Hemmert, Andrew C. and Cloud, Joann L. and Bellamkonda, Satya and Oswald, Cody and Lo, Eric and Nabeta, Henry and Kiggundu, Reuben and Akampurira, Andrew and Musubire, Abdu and Williams, Darlisha A. and Meya, David B. and Boulware, David R. and , A. S. T. R. O.-C. M. Team}, + institution = {Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA.}, + journal = {Diagn Microbiol Infect Dis}, + language = {eng}, + medline-pst = {aheadofprint}, + month = {Dec}, + pmid = {26711635}, + title = {Diagnostic performance of a multiplex PCR assay for meningitis in an HIV-infected population in Uganda.}, + year = {2015} +} \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml new file mode 100644 index 000000000000..3b64f43676f5 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml @@ -0,0 +1,230 @@ + + + + + + + 26711635 + + 2015 + 12 + 29 + + + 2015 + 12 + 30 + +
    + + 1879-0070 + + + 2015 + Dec + 1 + + + Diagnostic microbiology and infectious disease + Diagn. Microbiol. Infect. Dis. + + Diagnostic performance of a multiplex PCR assay for meningitis in an HIV-infected population in Uganda. + + + + S0732-8893(15)00432-0 + 10.1016/j.diagmicrobio.2015.11.017 + + This abstract is a dummy. + + + + Rhein + Joshua + J + + Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA; Infectious Disease Institute, Makerere University, Kampala, Uganda. Electronic address: joshua.rhein@gmail.com. + + + + Bahr + Nathan C + NC + + Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA. + + + + Hemmert + Andrew C + AC + + BioFire Diagnostics, LLC, Salt Lake City, UT, USA. + + + + Cloud + Joann L + JL + + BioFire Diagnostics, LLC, Salt Lake City, UT, USA. + + + + Bellamkonda + Satya + S + + BioFire Diagnostics, LLC, Salt Lake City, UT, USA. + + + + Oswald + Cody + C + + BioFire Diagnostics, LLC, Salt Lake City, UT, USA. + + + + Lo + Eric + E + + BioFire Diagnostics, LLC, Salt Lake City, UT, USA. + + + + Nabeta + Henry + H + + Infectious Disease Institute, Makerere University, Kampala, Uganda. + + + + Kiggundu + Reuben + R + + Infectious Disease Institute, Makerere University, Kampala, Uganda. + + + + Akampurira + Andrew + A + + Infectious Disease Institute, Makerere University, Kampala, Uganda. + + + + Musubire + Abdu + A + + Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA; Infectious Disease Institute, Makerere University, Kampala, Uganda. + + + + Williams + Darlisha A + DA + + Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA; Infectious Disease Institute, Makerere University, Kampala, Uganda. + + + + Meya + David B + DB + + Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA; Infectious Disease Institute, Makerere University, Kampala, Uganda. + + + + Boulware + David R + DR + + Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA. + + + + ASTRO-CM Team + + + ENG + + JOURNAL ARTICLE + + + 2015 + 12 + 1 + +
    + + Diagn Microbiol Infect Dis + 8305899 + 0732-8893 + + + Cryptococcal meningitis + Diagnostics + HIV + Immunocompromised + Meningitis + PCR + +
    + + + + 2015 + 7 + 21 + + + 2015 + 11 + 17 + + + 2015 + 11 + 18 + + + 2015 + 12 + 30 + 6 + 0 + + + 2015 + 12 + 30 + 6 + 0 + + + 2015 + 12 + 30 + 6 + 0 + + + aheadofprint + + S0732-8893(15)00432-0 + 10.1016/j.diagmicrobio.2015.11.017 + 26711635 + + +
    + + +
    \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMalformedEntry.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMalformedEntry.xml new file mode 100644 index 000000000000..098eac24b637 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMalformedEntry.xml @@ -0,0 +1,4 @@ + + + wrong format + \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.bib new file mode 100644 index 000000000000..d1f3b6ffbc80 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.bib @@ -0,0 +1,4 @@ +% Encoding: UTF-8 + +@Article{, +} \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.xml new file mode 100644 index 000000000000..65fca5c28a42 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestMinimalEntry.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib new file mode 100644 index 000000000000..d27cd647e68a --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib @@ -0,0 +1,15 @@ +% Encoding: UTF-8 + +@Article{, + Title = {Formate assay in body fluids: application in methanol poisoning.}, + Author = {Makar, A. B. and McMartin, K. E. and Palese, M. and Tephly, T. R.}, + Journal = {Biochem Med}, + Year = {1999}, + Number = {2}, + Pages = {117--126}, + Volume = {13}, + Keywords = {Aldehyde Oxidoreductases, metabolism; Animals; Body Fluids, analysis; Carbon Dioxide, blood; Formates, blood/poisoning; Haplorhini; Humans; Hydrogen-Ion Concentration; Kinetics; Methanol, blood; Methods; Pseudomonas, enzymology}, + Language = {eng}, + Medline-pst = {ppublish}, + Pmid = {1} +} \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml new file mode 100644 index 000000000000..2a3e6ba030e4 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml @@ -0,0 +1,143 @@ + + + +1 + +1976 +01 +16 + + +1976 +01 +16 + + +2013 +11 +21 + +
    + +0006-2944 + +13 +2 + +1999 Spring + + +Biochemical medicine +Biochem Med + +Formate assay in body fluids: application in methanol poisoning. + +117-26 + + + +Makar +A B +AB + + +McMartin +K E +KE + + +Palese +M +M + + +Tephly +T R +TR + + +eng + +Journal Article +Research Support, U.S. Gov't, P.H.S. + +
    + +UNITED STATES +Biochem Med +0151424 +0006-2944 + + + +0 +Formates + + +142M471B3J +Carbon Dioxide + + +EC 1.2.- +Aldehyde Oxidoreductases + + +Y4S76JWI15 +Methanol + + +IM + + +Aldehyde Oxidoreductases +metabolism + + +Animals + + +Body Fluids +analysis + + +Carbon Dioxide +blood + + +Formates +blood +poisoning + + +Haplorhini + + +Humans + + +Hydrogen-Ion Concentration + + +Kinetics + + +Methanol +blood + + +Methods + + +Pseudomonas +enzymology + + +
    + +ppublish + +1 + + +
    +
    \ No newline at end of file From 4aa51a3df8738cc6bc7de55e62f45468b0aeec15 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 23 May 2016 13:49:06 +0200 Subject: [PATCH 090/268] Fix #1412: Save action *protect terms* protects terms within words unecessarily --- CHANGELOG.md | 1 + .../logic/formatter/casechanger/ProtectTermsFormatter.java | 2 +- .../logic/formatter/casechanger/ProtectTermsFormatterTest.java | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fefbcd836f7..3e66ad17cbf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1394](https://github.com/JabRef/jabref/issues/1394): Personal journal abbrevations could not be saved - Fixed [#1400](https://github.com/JabRef/jabref/issues/1400): Detect path constructs wrong path for Windows - Fixed [#973](https://github.com/JabRef/jabref/issues/973): Add additional DOI field for English version of MS Office 2007 XML +- Fixed [#1412](https://github.com/JabRef/jabref/issues/1412): Save action *protect terms* protects terms within words unecessarily ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatter.java index cd744bef627f..a72f14aa0573 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatter.java @@ -30,7 +30,7 @@ private String format(String text, List listOfWords) { // For each word in the list for (String listOfWord : listOfWords) { // Add {} if the character before is a space, -, /, (, [, ", or } or if it is at the start of the string but not if it is followed by a } - result = result.replaceAll("(^|[- /\\[(}\"])" + listOfWord + "($|[^}])", "$1\\{" + listOfWord + "\\}$2"); + result = result.replaceAll("(^|[- /\\[(}\"])" + listOfWord + "($|[^a-zA-Z}])", "$1\\{" + listOfWord + "\\}$2"); } return result; } diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java index 6a079361b98e..cf31ae6ae35f 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java @@ -18,6 +18,8 @@ public void test() { assertEquals("{VLSI}", formatter.format("{VLSI}")); assertEquals("VLsI", formatter.format("VLsI")); assertEquals("{VLSI} {VLSI}", formatter.format("VLSI {VLSI}")); + assertEquals("{BPEL}", formatter.format("{BPEL}")); + assertEquals("{Testing BPEL Engine Performance: A Survey}", formatter.format("{Testing BPEL Engine Performance: A Survey}")); } @Test From a84502158b8d6be2feb9c2b8b783d41f78c7d8d6 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Mon, 23 May 2016 16:56:37 +0200 Subject: [PATCH 091/268] Also write newline if save actions are set to disabled --- src/main/java/net/sf/jabref/MetaData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index d99b893a39bd..b8eb006a768e 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -357,7 +357,7 @@ public Map serialize() { stringBuilder.append(StringUtil.quote(dataItem, ";", '\\')).append(";"); //in case of save actions, add an additional newline after the enabled flag - if (metaItem.getKey().equals(SAVE_ACTIONS) && "enabled".equals(dataItem)) { + if (metaItem.getKey().equals(SAVE_ACTIONS) && ("enabled".equals(dataItem) || "disabled".equals(dataItem))) { stringBuilder.append(Globals.NEWLINE); } } From 8be459bb9f2701d7f400d2a5e4c80396921433c1 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Mon, 23 May 2016 22:55:35 +0200 Subject: [PATCH 092/268] Fix #1420 Auto downloader should respect file pattern and propose correct filename --- CHANGELOG.md | 1 + .../jabref/external/DownloadExternalFile.java | 4 +- .../jabref/external/DroppedFileHandler.java | 2 +- .../sf/jabref/external/MoveFileAction.java | 2 +- .../logic/cleanup/RenamePdfCleanup.java | 2 +- .../net/sf/jabref/logic/util/io/FileUtil.java | 3 +- .../sf/jabref/logic/util/io/FileUtilTest.java | 44 +++++++++++++++++++ 7 files changed, 52 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e66ad17cbf5..1ff5fd6816f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1400](https://github.com/JabRef/jabref/issues/1400): Detect path constructs wrong path for Windows - Fixed [#973](https://github.com/JabRef/jabref/issues/973): Add additional DOI field for English version of MS Office 2007 XML - Fixed [#1412](https://github.com/JabRef/jabref/issues/1412): Save action *protect terms* protects terms within words unecessarily +- Fixed [#1420](https://github.com/JabRef/jabref/issues/1420): Auto downloader should respect file pattern and propose correct filename ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java index 140502dd670a..c0d0e6b0782d 100644 --- a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java +++ b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java @@ -26,6 +26,7 @@ import javax.swing.SwingUtilities; import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.FileListEntryEditor; @@ -267,7 +268,8 @@ private void downloadFinished() { } // FIXME: will break download if no bibtexkey is present! private String getSuggestedFileName(String suffix) { - String plannedName = bibtexKey == null ? "set-filename" : bibtexKey; + String plannedName = FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), frame.getCurrentBasePanel().getSelectedEntries().get(0), Globals.journalAbbreviationLoader.getRepository()); + if (!suffix.isEmpty()) { plannedName += "." + suffix; } diff --git a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java index 217e3ca9d88a..c8f09083c516 100644 --- a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java +++ b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java @@ -350,7 +350,7 @@ private boolean showLinkMoveCopyRenameDialog(String linkFileName, ExternalFileTy renameCheckBox.setText(Localization.lang("Rename file to").concat(": ")); // Determine which name to suggest: - String targetName = FileUtil.getLinkedFileName(database, entry, Globals.journalAbbreviationLoader.getRepository()); + String targetName = FileUtil.createFileNameFromPattern(database, entry, Globals.journalAbbreviationLoader.getRepository()); renameToTextBox.setText(targetName.concat(".").concat(fileType.getExtension())); diff --git a/src/main/java/net/sf/jabref/external/MoveFileAction.java b/src/main/java/net/sf/jabref/external/MoveFileAction.java index 37766f28c3fd..23caa58e7ef0 100644 --- a/src/main/java/net/sf/jabref/external/MoveFileAction.java +++ b/src/main/java/net/sf/jabref/external/MoveFileAction.java @@ -110,7 +110,7 @@ public void actionPerformed(ActionEvent event) { if (toFileDir) { // Determine which name to suggest: String suggName = FileUtil - .getLinkedFileName(eEditor.getDatabase(), eEditor.getEntry(), + .createFileNameFromPattern(eEditor.getDatabase(), eEditor.getEntry(), Globals.journalAbbreviationLoader.getRepository()) .concat(entry.type.isPresent() ? "." + entry.type.get().getExtension() : ""); CheckBoxMessage cbm = new CheckBoxMessage(Localization.lang("Move file to file directory?"), diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java index 7f511b4ace70..b8bf7331429b 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java @@ -59,7 +59,7 @@ public List cleanup(BibEntry entry) { } StringBuilder newFilename = new StringBuilder( - FileUtil.getLinkedFileName(databaseContext.getDatabase(), entry, repository)); + FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), entry, repository)); //Add extension to newFilename newFilename.append('.').append(FileUtil.getFileExtension(realOldFilename).orElse("pdf")); 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 4ba686095dbf..bc165632dcfb 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 @@ -389,8 +389,7 @@ public static List getListOfLinkedFiles(List bes, List f * @param repository * @return a suggested fileName */ - public static String getLinkedFileName(BibDatabase database, BibEntry entry, - JournalAbbreviationRepository repository) { + public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, JournalAbbreviationRepository repository) { String targetName = entry.getCiteKey() == null ? "default" : entry.getCiteKey(); StringReader sr = new StringReader(Globals.prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)); Layout layout = null; diff --git a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java index 8ca96d10b666..8a74ee0dde27 100644 --- a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java @@ -5,12 +5,56 @@ import java.util.Arrays; import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.model.entry.BibEntry; + +import org.junit.After; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class FileUtilTest { + @Before + public void setUp() { + Globals.prefs = mock(JabRefPreferences.class); + Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(Globals.prefs); + } + + @After + public void tearDown() { + Globals.prefs = null; + Globals.journalAbbreviationLoader = null; + } + + @Test + public void testGetLinkedFileNameDefault() { + // bibkey - title + when(Globals.prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)).thenReturn("\\bibtexkey\\begin{title} - \\format[RemoveBrackets]{\\title}\\end{title}"); + + BibEntry entry = new BibEntry(); + entry.setCiteKey("1234"); + entry.setField("title", "mytitle"); + + assertEquals("1234 - mytitle", FileUtil.createFileNameFromPattern(null, entry, Globals.journalAbbreviationLoader.getRepository())); + } + + @Test + public void testGetLinkedFileNameBibTeXKey() { + // bibkey + when(Globals.prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)).thenReturn("\\bibtexkey"); + + BibEntry entry = new BibEntry(); + entry.setCiteKey("1234"); + entry.setField("title", "mytitle"); + + assertEquals("1234", FileUtil.createFileNameFromPattern(null, entry, Globals.journalAbbreviationLoader.getRepository())); + } @Test public void testGetFileExtensionSimpleFile() { From 09e5e04d56ef352ce4ce2c3261a691f6bc7c0f45 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 24 May 2016 12:06:25 +0200 Subject: [PATCH 093/268] Remove expandAuthorInitials again (#1442) * Remove expandAuthorInitials again --- .../importer/fileformat/MedlineHandler.java | 1 - .../jabref/logic/util/strings/StringUtil.java | 46 ------------------- 2 files changed, 47 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java index 5b7a9f8a6430..d9bf5a553ee9 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java @@ -229,7 +229,6 @@ public void endElement(String uri, String localName, String qName) { if (!"".equals(author)) { b.setField("author", MedlineHandler.UNICODE_CONVERTER.format(author)); - // b.setField("author",Util.replaceSpecialCharacters(ImportFormatReader.expandAuthorInitials(author))); author = ""; } if (!"".equals(title)) { diff --git a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java index 12ff8c21e8aa..86a6e3bdf6cb 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java @@ -23,7 +23,6 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.model.entry.Author; import com.google.common.base.CharMatcher; @@ -626,51 +625,6 @@ public static String replaceSpecialCharacters(String s) { return result; } - /** - * Expand initials, e.g. EH Wissler -> E. H. Wissler or Wissler, EH -> Wissler, E. H. - * - * @param name - * @return The name after expanding initials. - */ - public static String expandAuthorInitials(String name) { - String[] authors = name.split(" and "); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < authors.length; i++) { - if (authors[i].contains(", ")) { - String[] names = authors[i].split(", "); - if (names.length > 0) { - sb.append(names[0]); - if (names.length > 1) { - sb.append(", "); - } - } - for (int j = 1; j < names.length; j++) { - if (j == 1) { - sb.append(Author.addDotIfAbbreviation(names[j])); - } else { - sb.append(names[j]); - } - if (j < (names.length - 1)) { - sb.append(", "); - } - } - } else { - String[] names = authors[i].split(" "); - if (names.length > 0) { - sb.append(Author.addDotIfAbbreviation(names[0])); - } - for (int j = 1; j < names.length; j++) { - sb.append(' '); - sb.append(names[j]); - } - } - if (i < (authors.length - 1)) { - sb.append(" and "); - } - } - return sb.toString().trim(); - } - /** * Return a String with n spaces * From f1c4521a30554a7c04d9b622c919160a1b86948a Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 24 May 2016 14:19:37 +0200 Subject: [PATCH 094/268] Fix imports and tests --- .../net/sf/jabref/cli/ArgumentProcessor.java | 17 +++-- .../jabref/exporter/SaveDatabaseAction.java | 1 + .../sf/jabref/external/MoveFileAction.java | 1 + .../sf/jabref/gui/FileListEntryEditor.java | 3 +- .../sf/jabref/gui/actions/BrowseAction.java | 14 +++-- .../gui/openoffice/StyleSelectDialog.java | 3 +- .../gui/plaintextimport/TextInputDialog.java | 1 + .../jabref/importer/ImportFormatReader.java | 11 +--- .../jabref/importer/OpenDatabaseAction.java | 62 ++++++++++++++++++- .../importer/fetcher/DOItoBibTeXFetcher.java | 15 +++-- .../importer/fetcher/MedlineFetcher.java | 1 + .../fileformat/BiblioscapeImporter.java | 6 +- .../importer/fileformat/FreeCiteImporter.java | 2 +- .../importer/fileformat/IsiImporter.java | 3 +- .../fileformat/MedlinePlainImporter.java | 4 +- .../importer/fileformat/MsBibImporter.java | 3 +- .../importer/fileformat/OvidImporter.java | 4 +- .../fileformat/PdfContentImporter.java | 11 ++-- .../importer/fileformat/PdfXmpImporter.java | 3 +- .../importer/fileformat/RepecNepImporter.java | 5 +- .../importer/fileformat/RisImporter.java | 4 +- src/main/resources/l10n/JabRef_da.properties | 3 +- src/main/resources/l10n/JabRef_de.properties | 3 +- src/main/resources/l10n/JabRef_en.properties | 3 +- src/main/resources/l10n/JabRef_es.properties | 3 +- src/main/resources/l10n/JabRef_fa.properties | 3 +- src/main/resources/l10n/JabRef_fr.properties | 3 +- src/main/resources/l10n/JabRef_in.properties | 3 +- src/main/resources/l10n/JabRef_it.properties | 3 +- src/main/resources/l10n/JabRef_ja.properties | 3 +- src/main/resources/l10n/JabRef_nl.properties | 3 +- src/main/resources/l10n/JabRef_no.properties | 3 +- .../resources/l10n/JabRef_pt_BR.properties | 3 +- src/main/resources/l10n/JabRef_ru.properties | 3 +- src/main/resources/l10n/JabRef_sv.properties | 3 +- src/main/resources/l10n/JabRef_tr.properties | 3 +- src/main/resources/l10n/JabRef_vi.properties | 3 +- src/main/resources/l10n/JabRef_zh.properties | 3 +- .../exporter/BibDatabaseWriterTest.java | 4 +- .../exporter/MSBibExportFormatTestFiles.java | 17 +++-- .../fileformat/BibTeXMLImporterTest.java | 32 +++------- .../fileformat/BibTeXMLImporterTestFiles.java | 39 +++++------- .../fileformat/BibTeXMLImporterTestTypes.java | 9 ++- .../fileformat/BiblioscapeImporterTest.java | 5 +- .../BiblioscapeImporterTestFiles.java | 10 +-- .../BiblioscapeImporterTestTypes.java | 5 +- .../fileformat/CopacImporterTest.java | 22 +++---- .../fileformat/CopacImporterTestFiles.java | 20 +++--- .../fileformat/EndnoteImporterTest.java | 10 +-- .../importer/fileformat/ImportFormatTest.java | 2 +- .../importer/fileformat/InspecImportTest.java | 5 +- .../importer/fileformat/IsiImporterTest.java | 6 +- .../fileformat/MedlineImporterTest.java | 30 +++------ .../fileformat/MedlineImporterTestFiles.java | 25 +++----- .../fileformat/MedlinePlainImporterTest.java | 58 ++++++++--------- .../fileformat/MsBibImporterTestfiles.java | 6 -- .../importer/fileformat/OvidImporterTest.java | 2 - .../fileformat/PdfXmpImporterTest.java | 6 +- .../fileformat/RISImporterTestFiles.java | 6 +- .../fileformat/RepecNepImporterTest.java | 2 - .../fileformat/SilverPlatterImporterTest.java | 6 -- .../jabref/logic/bibtex/BibEntryAssert.java | 48 ++++++++------ 62 files changed, 315 insertions(+), 285 deletions(-) diff --git a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java index 873d7b09cb78..32c7c29a413c 100644 --- a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java @@ -2,6 +2,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -515,14 +517,19 @@ private static Optional importFile(String argument) { if ((data.length > 1) && !"*".equals(data[1])) { System.out.println(Localization.lang("Importing") + ": " + data[0]); try { - List entries; + Path file; if (OS.WINDOWS) { - entries = Globals.IMPORT_FORMAT_READER.importFromFile(data[1], data[0], JabRefGUI.getMainFrame()); + file = Paths.get(data[0]); } else { - entries = Globals.IMPORT_FORMAT_READER.importFromFile(data[1], - data[0].replace("~", System.getProperty("user.home")), JabRefGUI.getMainFrame()); + file = Paths.get(data[0].replace("~", System.getProperty("user.home"))); } - return Optional.of(new ParserResult(entries)); + ParserResult result = Globals.IMPORT_FORMAT_READER.importFromFile(data[1], file); + + if(result.hasWarnings()) { + JabRefGUI.getMainFrame().showMessage(result.getErrorMessage()); + } + + return Optional.of(result); } catch (IllegalArgumentException ex) { System.err.println(Localization.lang("Unknown import format") + ": " + data[1]); return Optional.empty(); diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java index d15d3a639f4d..f5ec6b6f6afe 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; +import java.util.Collections; import javax.swing.JFileChooser; import javax.swing.JOptionPane; diff --git a/src/main/java/net/sf/jabref/external/MoveFileAction.java b/src/main/java/net/sf/jabref/external/MoveFileAction.java index e6d0d04ea794..9533006abf33 100644 --- a/src/main/java/net/sf/jabref/external/MoveFileAction.java +++ b/src/main/java/net/sf/jabref/external/MoveFileAction.java @@ -18,6 +18,7 @@ import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.Locale; diff --git a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java index 79772e48828e..2858bffadf34 100644 --- a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.IOException; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.regex.Pattern; @@ -364,7 +365,7 @@ public void actionPerformed(ActionEvent e) { } else { workingDir = new File(Globals.prefs.get(JabRefPreferences.FILE_WORKING_DIRECTORY)); } - String selection = FileDialogs.getNewFile(parent, initial, Collections.emptyList(), + String selection = FileDialogs.getNewFile(parent, workingDir, Collections.emptyList(), JFileChooser.OPEN_DIALOG, false); if (selection != null) { File newFile = new File(selection); diff --git a/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java b/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java index 3e07f1101d6a..88f5757e6623 100644 --- a/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/BrowseAction.java @@ -17,6 +17,8 @@ import java.awt.event.ActionEvent; import java.io.File; +import java.util.Collections; +import java.util.List; import javax.swing.AbstractAction; import javax.swing.JComponent; @@ -37,21 +39,21 @@ public final class BrowseAction extends AbstractAction { private final JTextField comp; private final boolean dir; private final JComponent focusTarget; - private final String extension; + private final List extension; public static BrowseAction buildForDir(JFrame frame, JTextField tc) { - return new BrowseAction(frame, tc, true, null, ""); + return new BrowseAction(frame, tc, true, null, Collections.emptyList()); } public static BrowseAction buildForDir(JTextField tc) { - return new BrowseAction(null, tc, true, null, ""); + return new BrowseAction(null, tc, true, null, Collections.emptyList()); } public static BrowseAction buildForFile(JTextField tc) { - return new BrowseAction(null, tc, false, null, ""); + return new BrowseAction(null, tc, false, null, Collections.emptyList()); } - public static BrowseAction buildForFile(JTextField tc, JComponent focusTarget, String extension) { + public static BrowseAction buildForFile(JTextField tc, JComponent focusTarget, List extension) { return new BrowseAction(null, tc, false, focusTarget, extension); } @@ -59,7 +61,7 @@ public static BrowseAction buildForDir(JTextField tc, JComponent focusTarget) { return new BrowseAction(null, tc, true, focusTarget, null); } - private BrowseAction(JFrame frame, JTextField tc, boolean dir, JComponent focusTarget, String extension) { + private BrowseAction(JFrame frame, JTextField tc, boolean dir, JComponent focusTarget, List extension) { super(Localization.lang("Browse")); this.frame = frame; this.dir = dir; diff --git a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java index 667597e85a71..522b4baaf910 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java @@ -23,6 +23,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; +import java.util.Collections; import java.util.Objects; import java.util.Optional; @@ -497,7 +498,7 @@ public AddFileDialog() { super(diag, Localization.lang("Add style file"), true); JButton browse = new JButton(Localization.lang("Browse")); - browse.addActionListener(BrowseAction.buildForFile(newFile, null, ".jstyle")); + browse.addActionListener(BrowseAction.buildForFile(newFile, null, Collections.singletonList(".jstyle"))); // Build content panel FormBuilder builder = FormBuilder.create(); diff --git a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java index 6e06262ed5ea..73eb5c7a1804 100644 --- a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java +++ b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java @@ -120,6 +120,7 @@ import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.util.component.OverlayPanel; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.FreeCiteImporter; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; diff --git a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java index 3e559bf4b759..a5d099234b40 100644 --- a/src/main/java/net/sf/jabref/importer/ImportFormatReader.java +++ b/src/main/java/net/sf/jabref/importer/ImportFormatReader.java @@ -15,15 +15,9 @@ */ package net.sf.jabref.importer; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -52,6 +46,7 @@ import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabases; import net.sf.jabref.model.entry.BibEntry; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index b7d929e37123..b485c9832c7d 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -44,7 +44,7 @@ import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.undo.NamedCompound; -import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.importer.fileformat.BibtexImporter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileBasedLock; import net.sf.jabref.logic.util.strings.StringUtil; @@ -348,4 +348,64 @@ public static ParserResult loadDatabase(File fileToOpen, Charset defaultEncoding return result; } + + /** + * Load database (bib-file) or, if there exists, a newer autosave version, unless the flag is set to ignore the autosave + * + * @param name Name of the bib-file to open + * @param ignoreAutosave true if autosave version of the file should be ignored + * @return ParserResult which never is null + */ + + public static ParserResult loadDatabaseOrAutoSave(String name, boolean ignoreAutosave) { + // String in OpenDatabaseAction.java + LOGGER.info("Opening: " + name); + File file = new File(name); + if (!file.exists()) { + ParserResult pr = new ParserResult(null, null, null); + pr.setFile(file); + pr.setInvalid(true); + LOGGER.error(Localization.lang("Error") + ": " + Localization.lang("File not found")); + return pr; + + } + try { + + if (!ignoreAutosave) { + boolean autoSaveFound = AutoSaveManager.newerAutoSaveExists(file); + if (autoSaveFound) { + // We have found a newer autosave. Make a note of this, so it can be + // handled after startup: + ParserResult postp = new ParserResult(null, null, null); + postp.setPostponedAutosaveFound(true); + postp.setFile(file); + return postp; + } + } + + if (!FileBasedLock.waitForFileLock(file, 10)) { + LOGGER.error(Localization.lang("Error opening file") + " '" + name + "'. " + + "File is locked by another JabRef instance."); + return ParserResult.getNullResult(); + } + + Charset encoding = Globals.prefs.getDefaultEncoding(); + ParserResult pr = OpenDatabaseAction.loadDatabase(file, encoding); + pr.setFile(file); + if (pr.hasWarnings()) { + for (String aWarn : pr.warnings()) { + LOGGER.warn(aWarn); + } + } + return pr; + } catch (Throwable ex) { + ParserResult pr = new ParserResult(null, null, null); + pr.setFile(file); + pr.setInvalid(true); + pr.setErrorMessage(ex.getMessage()); + LOGGER.info("Problem opening .bib-file", ex); + return pr; + } + + } } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index 08d9f8a1e327..d83c1c771945 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -22,28 +22,27 @@ import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.Objects; import java.util.Optional; -import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import net.sf.jabref.importer.*; -import net.sf.jabref.importer.fileformat.BibtexParser; -import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpFiles; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; +import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.logic.util.DOI; +import net.sf.jabref.model.entry.BibEntry; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; public class DOItoBibTeXFetcher implements EntryFetcher { private static final Log LOGGER = LogFactory.getLog(DOItoBibTeXFetcher.class); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java index 37035a737cb9..586870b691aa 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java @@ -32,6 +32,7 @@ import net.sf.jabref.gui.help.HelpFiles; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.MedlineImporter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java index 6ab614d3d79f..29b8d4290c6b 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java @@ -17,15 +17,13 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; /** diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index 71f922db3338..5f654facda35 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -36,7 +36,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java index 3304ee706ee1..5b4db6b86615 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java @@ -25,8 +25,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.formatter.casechanger.TitleCaseFormatter; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.MonthUtil; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index b9f83cfefd76..00215f82b9d2 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -19,7 +19,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -27,8 +26,7 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java index b33e3d0706cf..52d11a7a5d80 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java @@ -23,9 +23,8 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.msbib.MSBibDatabase; -import net.sf.jabref.model.entry.BibEntry; import org.w3c.dom.Document; import org.xml.sax.InputSource; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java index b80ca64802cd..de8fe3d3201e 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java @@ -17,7 +17,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -25,8 +24,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index a1f5271908e8..a9a412ee9755 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -1,17 +1,18 @@ package net.sf.jabref.importer.fileformat; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportInspector; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fetcher.DOItoBibTeXFetcher; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.DOI; @@ -22,8 +23,6 @@ import net.sf.jabref.model.entry.EntryType; import com.google.common.base.Strings; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.util.PDFTextStripper; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java index c66360a99a42..14bb88b624c5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java @@ -22,10 +22,9 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.xmp.XMPUtil; -import net.sf.jabref.model.entry.BibEntry; /** * Wraps the XMPUtility function to be used as an ImportFormat. diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index 9ffa4bc74fcb..04871c5d41e5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -25,12 +25,13 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; +import java.util.Objects; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java index c28c126b02ff..667c2359df96 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java @@ -17,7 +17,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -25,8 +24,7 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.MonthUtil; diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index e6fa85d381b5..3803774f1fad 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1228,7 +1228,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Get_BibTeX_entry_from_DOI= Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= @@ -1686,3 +1685,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index e3db4c5d1f8e..b4d9f8187004 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1936,7 +1936,6 @@ Searching...=Suche_läuft... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Sie_haben_mehr_als_%0_Einträge_zum_Download_ausgewählt._Einige_Webseiten_könnten_zu_viele_Downloads_blockieren._Möchten_Sie_fortfahren? Confirm_selection=Auswahl_bestätigen Unknown_DOI\:_'%0'.=Unbekannte_DOI\:_'0%'. -Get_BibTeX_entry_from_DOI=BibTeX-Eintrag_aus_DOI_erstellen Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Hoch-_und_tiefgestellte_Zeichen_in_eine_Gleichung_konvertieren_und_nicht_als_Text_darstellen Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Nach_der_Suche_{}_zu_festgesetzten_Titelworten_hinzufügen,_um_Groß-/Kleinschreibung_beizubehalten Import_conversions=Konvertierungen_importieren @@ -2402,3 +2401,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index a12aa039044d..af02f181a467 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1835,7 +1835,6 @@ Searching...=Searching... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue? Confirm_selection=Confirm_selection Unknown_DOI\:_'%0'.=Unknown_DOI\:_'%0'. -Get_BibTeX_entry_from_DOI=Get_BibTeX_entry_from_DOI Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case Import_conversions=Import_conversions @@ -2258,3 +2257,5 @@ Copied_version_to_clipboard=Copied_version_to_clipboard BibTeX_key=BibTeX_key Message=Message + +Decryption_not_supported.=Decryption_not_supported. diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index a0d9f6d049ee..02d240878c70 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1136,7 +1136,6 @@ Searching...=Buscando... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Ha_seleccionado_más_de_%0_entradas_para_descargar._Algunos_sitios_web_podrían_bloquearle_si_hace_demasiadas_descargas._¿Desea_continuar? Confirm_selection=Confirmar_selección Unknown_DOI\:_'%0'.=DOI_desconocido\:_'%0'. -Get_BibTeX_entry_from_DOI=Obtener_entrada_BibTeX_desde_DOI Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Preferir_convertir_subíndices_y_superíndices_a_ecuaciónantes_que_a_texto Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Añadir_{}_para_especificar_las_palabras_del_título_para_mantener_mayúsculas/minúsculas_correctamente Import_conversions=Importar_conversiones @@ -1587,3 +1586,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index cbec249fc1b5..7a87a29200c4 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1890,7 +1890,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Get_BibTeX_entry_from_DOI= Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= @@ -2373,3 +2372,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 161780ace8c4..7fb665449433 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1168,7 +1168,6 @@ Searching...=Recherche... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Vous_avez_sélectionné_plus_de_%0_entrées_à_télécharger._Certains_sites_web_pourraient_vous_bloquer_si_vous_effectuez_de_trop_nombreux_et_rapides_téléchargements._Voulez-vous_continuer? Confirm_selection=Confirmez_la_sélection Unknown_DOI\:_'%0'.=DOI_inconnu_\:_'%0'. -Get_BibTeX_entry_from_DOI=Obtenir_l'entrée_BibTeX_à_partir_du_DOI Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Conversion_des_indices_et_exposants_en_équations_plutôt_qu'en_texte Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Ajouter_{}_aux_mots_du_titre_spécifiés_lors_d'une_recherche_pour_préserver_la_casse_correcte Import_conversions=Importer_les_conversions @@ -1631,3 +1630,5 @@ Message=Message Get_fulltext=Obtenir_le_document Download_from_URL=Télécharger_depuis_l'URL + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 815cd8b7c09f..dd570bfda3e3 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1145,7 +1145,6 @@ Searching...=Sedang_mencari... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Anda_memilih_lebih_dari_%0_entri._Sejumlah_situs_web_akan_memblokir_anda_kalau_melakukan_terlalu_banyak_pemuatturunan_dengan_cepat._Apa_mau_teruskan? Confirm_selection=Mengkonfirmasi_pilihan Unknown_DOI\:_'%0'.=DOI_tidak_dikenal\:_'%0'. -Get_BibTeX_entry_from_DOI=Dapatkan_entri_BibTeX_dari_DOI Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions=Impor_konversi @@ -1606,3 +1605,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index ab79f6d78767..4a968c509d17 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1246,7 +1246,6 @@ Searching...=Ricerca_in_corso... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Sono_state_selezionate_pi\u00f9_di_%0_voci_da_scaricare._Alcuni_siti_potrebbero_bloccare_la_connessione_se_si_eseguono_scaricamenti_troppo_numerosi_e_rapidi._Continuare? Confirm_selection=Conferma_la_selezione Unknown_DOI\:_'%0'.=DOI_sconosciuto\:_'%0' -Get_BibTeX_entry_from_DOI=Recupera_la_voce_BibTeX_dal_DOI Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Conversione_di_apici_e_pedici_in_equazioni_piuttosto_che_in_testo. Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Aggiungere_{}_alle_parole_del_titolo_specificate_per_mantenere_la_corretta_capitalizzazione_nella_ricerca. Import_conversions=Importare_le_conversioni @@ -1706,3 +1705,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index d266fbb4c570..57f75f7881af 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1917,7 +1917,6 @@ Searching...=検索中... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=ダウンロードする項目を%0個以上選択しました。あまりに多くのダウンロードを急に行うと、其れをブロックするウェブサイトもあります。続けますか? Confirm_selection=選択範囲を確認 Unknown_DOI\:_'%0'.=「%0」は既知のDOIではありません -Get_BibTeX_entry_from_DOI=DOIからBibTeX項目を取得 Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=上添字及び下添字をテキストではなく数式に変換する Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=大小文字を正しく維持するため、検索中に指定したタイトル語に{}を付け加える Import_conversions=読み込み時変換 @@ -2351,3 +2350,5 @@ Message=メッセージ Get_fulltext=フルテキストを得る Download_from_URL=URLからダウンロード + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 8493ea103304..1f60cf878dc4 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1919,7 +1919,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.=Unbekende_DOI\:_'%0'. -Get_BibTeX_entry_from_DOI= Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= @@ -2382,3 +2381,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 08ee7d9c0611..c71a623efe3a 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2314,7 +2314,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Get_BibTeX_entry_from_DOI= Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= @@ -2778,3 +2777,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index fe35567b5ebf..39cf57b780c4 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1143,7 +1143,6 @@ Searching...=Buscando... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Você_selecionou_mais_de_%0_entradas_para_download._Alguns_sites_podem_bloquear_seu_acesso_se_você_fizer_muitos_downloads_num_período_curto_de_tempo._Deseja_continuar_mesmo_assim? Confirm_selection=Confirmar_seleção Unknown_DOI\:_'%0'.=DOI_desconhecido\:_'%0'. -Get_BibTeX_entry_from_DOI=Obter_referência_a_partir_do_DOI. Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Dar_preferência_à_conversão_de_subscritos_sobrescritos_para_equações_ao_invés_de_textos Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Adicione_{}_às_palavras_do_título_na_busca_para_manter_maiúsculas_minúsculas Import_conversions=Importar_conversões @@ -1600,3 +1599,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 3fc1069a8429..153a9f546306 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1887,7 +1887,6 @@ Searching...=Выполняется_поиск... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Выбрано_более_%0_записей_для_загрузки._Возможна_блокировка_пользователя_некоторыми_веб-сайтами_при_большом_числе_быстрых_загрузок._Продолжить? Confirm_selection=Подтвердить_выбор Unknown_DOI\:_'%0'.=Неизвестный_DOI\:_'%0'. -Get_BibTeX_entry_from_DOI=Получить_запись_BibTeX_из_DOI Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Преобразовывать_надстрочный_и_подстрочный_индекс_в_формулу_вместо_текста Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Добавлять_{}_к_указанным_заглавным_словам_при_поиске_для_соблюдения_правильности_регистра Import_conversions=Импорт_преобразований @@ -2350,3 +2349,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 9c1b7e41d437..1563e3352d4b 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -533,7 +533,6 @@ Generate_now=Generera_nu Generated_BibTeX_key_for=Genererade_BibTeX-nycklar_för Generating_BibTeX_key_for=Genererar_BibTeX-nycklar_för Get_BibTeX_data_from_DOI=Hämta_BibTeX-data_från_DOI -Get_BibTeX_entry_from_DOI=Hämta_BibTeX-post_från_DOI Get_BibTeX_entry_from_DiVA=Hämta_BibTeX-post_från_DIVA Grab= Gray_out_entries_not_in_group_selection=Skugga_poster_som_inte_är_med_i_en_grupp @@ -1545,3 +1544,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 0fdeac046d5f..63b7b4fde802 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1165,7 +1165,6 @@ Searching...=Arıyor... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=İndirmek_için_%0'dan_fazla_girdi_seçtiniz._Çok_sayıda_hızlı_indirme_yaparsanız_bazı_web_siteleri_sizi_bloke_edebilir._Devam_etmek_istiyor_musunuz? Confirm_selection=Seçimi_onayla Unknown_DOI\:_'%0'.=Bilinmeyen_DOI\:_'%0'. -Get_BibTeX_entry_from_DOI=BibTeX_girdisini_DOI'den_al Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Alt_ve_üstsimgeleri_metinden_ziyade_denklemlere_dönüştürmeyi_tercih_et Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Aramada_doğru_küçük_büyük_harf_seçimi_için_belirli_başlık_sözcüklerine_{}_ekleyin Import_conversions=Dönüşümleri_içe_aktar @@ -1619,3 +1618,5 @@ Message=Mesaj Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 1644fb3422e2..1dad633d9909 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1913,7 +1913,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Get_BibTeX_entry_from_DOI= Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= @@ -2374,3 +2373,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 5982ba1afbc3..30c6ac86d07a 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1219,7 +1219,6 @@ Searching...=正在搜索... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection=确认选择 Unknown_DOI\:_'%0'.= -Get_BibTeX_entry_from_DOI=从_DOI_中获取_BibTeX_记录 Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=将上下标转换成公式而不是文本 Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=搜索时为特殊的标题单词添加_{}_以保证大小写正确 Import_conversions=导入约定 @@ -1613,3 +1612,5 @@ Message= Get_fulltext= Download_from_URL= + +Decryption_not_supported.= diff --git a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java index f1366255d5e1..bfaa1c0535bc 100644 --- a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java @@ -1,11 +1,11 @@ package net.sf.jabref.exporter; -import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; @@ -16,9 +16,9 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.config.SaveOrderConfig; diff --git a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java index 3e3e5287a26f..3c140f8bc551 100644 --- a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java +++ b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java @@ -2,7 +2,7 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; @@ -16,7 +16,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.importer.fileformat.BibtexImporter; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; @@ -32,7 +31,6 @@ import org.junit.runners.Parameterized.Parameters; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; @RunWith(Parameterized.class) public class MSBibExportFormatTestFiles { @@ -71,14 +69,15 @@ public void setUp() throws Exception { } @Test - public final void testPerformExport() throws IOException { + public final void testPerformExport() throws IOException, URISyntaxException { String xmlFileName = filename.replace(".bib", ".xml"); + Path importFile = Paths.get(MSBibExportFormatTestFiles.class.getResource(filename).toURI()); String tempFilename = tempFile.getCanonicalPath(); - try (InputStream bibIn = MSBibExportFormat.class.getResourceAsStream(filename)) { - List entries = testImporter.importEntries(bibIn, new OutputPrinterToNull()); - assertNotNull(entries); - msBibExportFormat.performExport(databaseContext, tempFile.getPath(), charset, entries); - } + List entries = testImporter.importDatabase(importFile, Charset.defaultCharset()).getDatabase() + .getEntries(); + + msBibExportFormat.performExport(databaseContext, tempFile.getPath(), charset, entries); + List expected = Files.readAllLines(Paths.get(PATH_TO_FILE + xmlFileName)); List exported = Files.readAllLines(Paths.get(tempFilename)); assertEquals(expected, exported); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java index 66783ffafdea..5219196fed48 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java @@ -1,7 +1,7 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -13,14 +13,11 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; -import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) @@ -34,10 +31,10 @@ public class BibTeXMLImporterTest { * @return A list of Names * @throws IOException */ - public List getTestFiles() throws IOException { - List files = new ArrayList<>(); + public List getTestFiles() throws IOException { + List files = new ArrayList<>(); try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(FILEFORMAT_PATH))) { - stream.forEach(n -> files.add(n.getFileName().toString())); + stream.forEach(files::add); } return files; @@ -48,17 +45,6 @@ public static void setUp() { Globals.prefs = JabRefPreferences.getInstance(); } - @Test - public void testExceptionOnInputStream() throws IOException { - try (InputStream is = Mockito.mock(InputStream.class)) { - Mockito.doThrow(new IOException()).when(is).read(); - - BibTeXMLImporter importer = new BibTeXMLImporter(); - List entry = importer.importEntries(is, new OutputPrinterToNull()); - Assert.assertTrue(entry.isEmpty()); - } - } - @Test public void testGetItemsEmpty() { BibTeXMLHandler handler = new BibTeXMLHandler(); @@ -74,20 +60,18 @@ public void testGetFormatName() { @Test public void testGetCLIId() { BibTeXMLImporter importer = new BibTeXMLImporter(); - Assert.assertEquals("bibtexml", importer.getCLIId()); + Assert.assertEquals("bibtexml", importer.getId()); } @Test public void testIsRecognizedFormatReject() throws IOException { BibTeXMLImporter importer = new BibTeXMLImporter(); - List list = getTestFiles().stream().filter(n -> !n.startsWith("BibTeXMLImporterTest")) + List list = getTestFiles().stream().filter(n -> !n.getFileName().toString().startsWith("BibTeXMLImporterTest")) .collect(Collectors.toList()); - for (String str : list) { - try (InputStream is = BibTeXMLImporter.class.getResourceAsStream(str)) { - Assert.assertFalse(importer.isRecognizedFormat(is)); - } + for (Path file : list) { + Assert.assertFalse(file.toString(), importer.isRecognizedFormat(file, Charset.defaultCharset())); } } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java index 16ab0971ac60..fc2c81a704e7 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java @@ -1,7 +1,7 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -15,7 +15,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; @@ -36,7 +35,7 @@ public class BibTeXMLImporterTestFiles { private BibTeXMLImporter bibtexmlImporter; @Parameter - public String fileName; + public Path importFile; @Before @@ -46,36 +45,32 @@ public void setUp() { } @Parameters(name = "{0}") - public static Collection fileNames() throws IOException { - List files = new ArrayList<>(); + public static Collection files() throws IOException { + List files = new ArrayList<>(); try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(FILEFORMAT_PATH))) { - stream.forEach(n -> files.add(n.getFileName().toString())); + stream.forEach(files::add); } - return files.stream().filter(n -> n.startsWith("BibTeXMLImporterTest")).filter(n -> n.endsWith(".xml")) + return files.stream().filter(n -> n.getFileName().toString().startsWith("BibTeXMLImporterTest") && n.getFileName().toString().endsWith(".xml")) .collect(Collectors.toList()); } @Test public void testIsRecognizedFormat() throws IOException { - try (InputStream stream = BibTeXMLImporterTest.class.getResourceAsStream(fileName)) { - Assert.assertTrue(bibtexmlImporter.isRecognizedFormat(stream)); - } + Assert.assertTrue(bibtexmlImporter.isRecognizedFormat(importFile, Charset.defaultCharset())); } @Test public void testImportEntries() throws IOException { - try (InputStream bitexmlStream = BibTeXMLImporterTest.class.getResourceAsStream(fileName)) { - List bibtexmlEntries = bibtexmlImporter.importEntries(bitexmlStream, new OutputPrinterToNull()); + List bibtexmlEntries = bibtexmlImporter.importDatabase(importFile, Charset.defaultCharset()).getDatabase().getEntries(); - String bibFileName = fileName.replace(".xml", ".bib"); - while (PATTERN.matcher(bibFileName).find()) { - bibFileName = bibFileName.replaceFirst("[0123456789]", ""); - } - if (bibtexmlEntries.isEmpty()) { - Assert.assertEquals(Collections.emptyList(), bibtexmlEntries); - } else { - BibEntryAssert.assertEquals(BibTeXMLImporterTest.class, bibFileName, bibtexmlEntries); - } + String bibFileName = importFile.getFileName().toString().replace(".xml", ".bib"); + while (PATTERN.matcher(bibFileName).find()) { + bibFileName = bibFileName.replaceFirst("[0123456789]", ""); + } + if (bibtexmlEntries.isEmpty()) { + Assert.assertEquals(Collections.emptyList(), bibtexmlEntries); + } else { + BibEntryAssert.assertEquals(BibTeXMLImporterTest.class, bibFileName, bibtexmlEntries); } } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java index 4557c5605b55..e75d2475136a 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java @@ -1,8 +1,8 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; +import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.StringReader; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -10,7 +10,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -54,8 +53,8 @@ public void importConvertsToCorrectBibType() throws IOException { + "Java tricks\n" + "2016\n" + "\n" + "\n" + ""; - List bibEntries = bibteXMLImporter.importEntries( - new ByteArrayInputStream(bibteXMLInput.getBytes(StandardCharsets.UTF_8)), new OutputPrinterToNull()); + List bibEntries = bibteXMLImporter.importDatabase(new BufferedReader(new StringReader(bibteXMLInput))) + .getDatabase().getEntries(); BibEntry entry = new BibEntry(); entry.setField("author", "Max Mustermann"); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java index 9731f8672bcd..ac7baf87666e 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java @@ -1,11 +1,12 @@ package net.sf.jabref.importer.fileformat; -import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java index 3912b510477f..afc910ec2f0c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java @@ -1,22 +1,24 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.List; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) @@ -61,6 +63,6 @@ public void testIsRecognizedFormat() throws IOException { public void testImportEntries() throws IOException { List bsEntries = bsImporter.importDatabase(importFile, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(1, bsEntries.size()); - BibtexEntryAssert.assertEquals(BiblioscapeImporterTest.class, bibFile, bsEntries); + BibEntryAssert.assertEquals(BiblioscapeImporterTest.class, bibFile, bsEntries); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java index 8ee3e0aa8715..95a70c5f8046 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java @@ -1,8 +1,8 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; +import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.StringReader; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -10,7 +10,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java index 726e1df652ce..8ced65c08305 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java @@ -1,7 +1,8 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -13,8 +14,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -42,12 +43,6 @@ public static void setUp() { Globals.prefs = JabRefPreferences.getInstance(); } - @Test(expected = IOException.class) - public void testImportEntriesException() throws IOException { - CopacImporter importer = new CopacImporter(); - importer.importEntries(null, new OutputPrinterToNull()); - } - @Test public void testIsNotRecognizedFormat() throws IOException, URISyntaxException { CopacImporter importer = new CopacImporter(); @@ -60,13 +55,10 @@ public void testIsNotRecognizedFormat() throws IOException, URISyntaxException { } @Test - public void testImportEmptyEntries() throws IOException { + public void testImportEmptyEntries() throws IOException, URISyntaxException { CopacImporter importer = new CopacImporter(); - - try (InputStream is = CopacImporterTest.class.getResourceAsStream("Empty.txt")) { - List entries = importer.importEntries(is, new OutputPrinterToNull()); - Assert.assertEquals(0, entries.size()); - Assert.assertEquals(Collections.emptyList(), entries); - } + Path path = Paths.get(CopacImporterTest.class.getResource("Empty.txt").toURI()); + List entries = importer.importDatabase(path, Charset.defaultCharset()).getDatabase().getEntries(); + Assert.assertEquals(Collections.emptyList(), entries); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java index 0ef18788af1f..4c054737809b 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java @@ -2,6 +2,8 @@ import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -50,21 +52,17 @@ public static Collection fileNames() throws IOException { } @Test - public void testIsRecognizedFormat() throws IOException { - try (InputStream stream = CopacImporterTest.class.getResourceAsStream(fileName)) { - Assert.assertTrue(copacImporter.isRecognizedFormat(stream)); - } + public void testIsRecognizedFormat() throws IOException, URISyntaxException { + Path file = Paths.get(CopacImporterTest.class.getResource(fileName).toURI()); + Assert.assertTrue(copacImporter.isRecognizedFormat(file, Charset.defaultCharset())); } @Test - public void testImportEntries() throws IOException { + public void testImportEntries() throws IOException, URISyntaxException { String bibFileName = fileName.replace(".txt", ".bib"); - try (InputStream copacStream = CopacImporterTest.class.getResourceAsStream(fileName); - InputStream bibStream = BibtexImporterTest.class.getResourceAsStream(bibFileName)) { - BibEntryAssert.assertEquals(bibStream, copacStream, copacImporter); + try (InputStream bibStream = BibtexImporterTest.class.getResourceAsStream(bibFileName)) { + BibEntryAssert.assertEquals(bibStream, CopacImporterTest.class.getResource(fileName), copacImporter); } - } - -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index e07fdcbf4683..da2bd3b85058 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -1,15 +1,17 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; +import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.io.StringReader; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java index 8e148d54166f..a28fd996e779 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java @@ -76,7 +76,7 @@ public static Collection instancesToTest() { return Arrays.asList( new Object[]{new BiblioscapeImporter()}, new Object[]{new BibtexImporter()}, - new Object[]{new BibteXMLImporter()}, + new Object[]{new BibTeXMLImporter()}, new Object[]{new CopacImporter()}, new Object[]{new EndnoteImporter()}, new Object[]{new FreeCiteImporter()}, diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index 56b86359ba09..a423ec33e703 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -1,6 +1,6 @@ package net.sf.jabref.importer.fileformat; -import java.io.ByteArrayInputStream; +import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.net.URISyntaxException; @@ -13,7 +13,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; @@ -69,7 +68,7 @@ public void testCompleteBibtexEntryOnJournalPaperImport() throws IOException, UR expectedEntry.setField("volume", "19"); BibEntryAssert.assertEquals(Collections.singletonList(expectedEntry), - InspecImportTest.class.getResourceAsStream("InspecImportTest2.txt"), inspecImp); + InspecImportTest.class.getResource("InspecImportTest2.txt"), inspecImp); } @Test diff --git a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java index c796138fe1ea..6d7fe7fd59fd 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java @@ -1,14 +1,16 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.HashMap; import java.util.List; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java index 5a16d5c1f1be..0dcefbbd835c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java @@ -1,7 +1,7 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -13,14 +13,11 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; -import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import static org.junit.Assert.assertEquals; @@ -47,10 +44,10 @@ public class MedlineImporterTest { * @return A list of Names * @throws IOException */ - public List getTestFiles() throws IOException { - List files = new ArrayList<>(); + public List getTestFiles() throws IOException { + List files = new ArrayList<>(); try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(FILEFORMAT_PATH))) { - stream.forEach(n -> files.add(n.getFileName().toString())); + stream.forEach(files::add); } return files; } @@ -61,15 +58,6 @@ public void setUp() throws Exception { this.medlineImporter = new MedlineImporter(); } - @Test - public void testExceptionOnInputStream() throws IOException { - try (InputStream is = Mockito.mock(InputStream.class)) { - Mockito.doThrow(new IOException()).when(is).read(); - List entry = medlineImporter.importEntries(is, new OutputPrinterToNull()); - Assert.assertTrue(entry.isEmpty()); - } - } - @Test public void testGetItemsEmpty() { MedlineHandler handler = new MedlineHandler(); @@ -83,18 +71,16 @@ public void testGetFormatName() { @Test public void testGetCLIId() { - assertEquals("medline", medlineImporter.getCLIId()); + assertEquals("medline", medlineImporter.getId()); } @Test public void testIsRecognizedFormatReject() throws IOException { - List list = getTestFiles().stream().filter(n -> !n.startsWith("MedlineImporter")) + List list = getTestFiles().stream().filter(n -> !n.getFileName().toString().startsWith("MedlineImporter")) .collect(Collectors.toList()); - for (String str : list) { - try (InputStream is = MedlineImporter.class.getResourceAsStream(str)) { - Assert.assertFalse(medlineImporter.isRecognizedFormat(is)); - } + for (Path file : list) { + Assert.assertFalse(file.toString(), medlineImporter.isRecognizedFormat(file, Charset.defaultCharset())); } } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java index 333bbb6330b1..f0ada4dbeb4c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java @@ -1,7 +1,7 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -14,7 +14,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; @@ -37,7 +36,7 @@ public class MedlineImporterTestFiles { private MedlineImporter medlineImporter; @Parameter - public String fileName; + public Path importFile; @Before @@ -47,33 +46,29 @@ public void setUp() { } @Parameters(name = "{0}") - public static Collection fileNames() throws IOException { - List files = new ArrayList<>(); + public static Collection files() throws IOException { + List files = new ArrayList<>(); try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(FILEFORMAT_PATH))) { - stream.forEach(n -> files.add(n.getFileName().toString())); + stream.forEach(files::add); } - return files.stream().filter(n -> n.startsWith("MedlineImporterTest")).filter(n -> n.endsWith(".xml")) + return files.stream().filter(n -> n.getFileName().toString().startsWith("MedlineImporterTest") && n.getFileName().toString().endsWith(".xml")) .collect(Collectors.toList()); } @Test public void testIsRecognizedFormat() throws IOException { - try (InputStream stream = MedlineImporterTest.class.getResourceAsStream(fileName)) { - Assert.assertTrue(medlineImporter.isRecognizedFormat(stream)); - } + Assert.assertTrue(medlineImporter.isRecognizedFormat(importFile, Charset.defaultCharset())); } @Test @Ignore public void testImportEntries() throws IOException { - try (InputStream inputStream = MedlineImporterTest.class.getResourceAsStream(fileName)) { - List medlineEntries = medlineImporter.importEntries(inputStream, new OutputPrinterToNull()); - String bibFileName = fileName.replace(".xml", ".bib"); + List medlineEntries = medlineImporter.importDatabase(importFile, Charset.defaultCharset()).getDatabase().getEntries(); + String bibFileName = importFile.getFileName().toString().replace(".xml", ".bib"); if (medlineEntries.isEmpty()) { assertEquals(Collections.emptyList(), medlineEntries); } else { BibEntryAssert.assertEquals(MedlineImporterTest.class, bibFileName, medlineEntries); } - } } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index 1f3a7cee907c..dc795c78ffaf 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -14,7 +14,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; @@ -22,6 +21,8 @@ import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class MedlinePlainImporterTest { private MedlinePlainImporter importer; @@ -70,51 +71,51 @@ public void testImportMultipleEntriesInSingleFile() throws IOException, URISynta List entries = importer.importDatabase(inputFile, Charset.defaultCharset()).getDatabase() .getEntries(); - Assert.assertEquals(7, entries.size()); + assertEquals(7, entries.size()); BibEntry testEntry = entries.get(0); - Assert.assertEquals("article", testEntry.getType()); + assertEquals("article", testEntry.getType()); Assert.assertNull(testEntry.getField("month")); - Assert.assertEquals("Long, Vicky and Marland, Hilary", testEntry.getField("author")); - Assert.assertEquals( + assertEquals("Long, Vicky and Marland, Hilary", testEntry.getField("author")); + assertEquals( "From danger and motherhood to health and beauty: health advice for the factory girl in early twentieth-century Britain.", testEntry.getField("title")); testEntry = entries.get(1); - Assert.assertEquals("conference", testEntry.getType()); - Assert.assertEquals("06", testEntry.getField("month")); + assertEquals("conference", testEntry.getType()); + assertEquals("06", testEntry.getField("month")); Assert.assertNull(testEntry.getField("author")); Assert.assertNull(testEntry.getField("title")); testEntry = entries.get(2); - Assert.assertEquals("book", testEntry.getType()); - Assert.assertEquals( + assertEquals("book", testEntry.getType()); + assertEquals( "This is a Testtitle: This title should be appended: This title should also be appended. Another append to the Title? LastTitle", testEntry.getField("title")); testEntry = entries.get(3); - Assert.assertEquals("techreport", testEntry.getType()); + assertEquals("techreport", testEntry.getType()); Assert.assertNotNull(testEntry.getField("doi")); testEntry = entries.get(4); - Assert.assertEquals("inproceedings", testEntry.getType()); - Assert.assertEquals("Inproceedings book title", testEntry.getField("booktitle")); + assertEquals("inproceedings", testEntry.getType()); + assertEquals("Inproceedings book title", testEntry.getField("booktitle")); BibEntry expectedEntry5 = new BibEntry(); expectedEntry5.setType("proceedings"); expectedEntry5.setField("keywords", "Female"); - BibtexEntryAssert.assertEquals(expectedEntry5, entries.get(5)); + assertEquals(expectedEntry5, entries.get(5)); BibEntry expectedEntry6 = new BibEntry(); expectedEntry6.setType("misc"); expectedEntry6.setField("keywords", "Female"); - BibtexEntryAssert.assertEquals(expectedEntry6, entries.get(6)); + assertEquals(expectedEntry6, entries.get(6)); } @Test public void testEmptyFileImport() throws IOException { List emptyEntries = importer.importDatabase(readerForString("")).getDatabase().getEntries(); - Assert.assertEquals(Collections.emptyList(), emptyEntries); + assertEquals(Collections.emptyList(), emptyEntries); } @Test @@ -135,7 +136,7 @@ private void assertImportOfMedlineFileEqualsBibtexFile(String medlineFile, Strin try (InputStream nis = MedlinePlainImporter.class.getResourceAsStream(bibtexFile)) { List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertNotNull(entries); - Assert.assertEquals(1, entries.size()); + assertEquals(1, entries.size()); BibEntryAssert.assertEquals(nis, entries.get(0)); } } @@ -150,14 +151,13 @@ public void testMultiLineComments() throws IOException { + "UOF - Comment14" + "\n" + "SPIN- Comment15" + "\n" + "ORI - Comment16"); List actualEntries = importer.importDatabase(reader).getDatabase().getEntries(); - BibEntry expectedEntry = new BibEntry(); - expectedEntry.setField("comment", - "Comment1" + "\n" + "Comment2" + "\n" + "Comment3" + "\n" + "Comment4" + "\n" + "Comment5" + "\n" - + "Comment6" + "\n" + "Comment7" + "\n" + "Comment8" + "\n" + "Comment9" + "\n" - + "Comment10" + "\n" + "Comment11" + "\n" + "Comment12" + "\n" + "Comment13" + "\n" - + "Comment14" + "\n" + "Comment15" + "\n" + "Comment16"); - Assert.assertEquals(Collections.singletonList(expectedEntry), actualEntries); - } + BibEntry expectedEntry = new BibEntry(); + expectedEntry.setField("comment", + "Comment1" + "\n" + "Comment2" + "\n" + "Comment3" + "\n" + "Comment4" + "\n" + "Comment5" + "\n" + + "Comment6" + "\n" + "Comment7" + "\n" + "Comment8" + "\n" + "Comment9" + "\n" + + "Comment10" + "\n" + "Comment11" + "\n" + "Comment12" + "\n" + "Comment13" + "\n" + + "Comment14" + "\n" + "Comment15" + "\n" + "Comment16"); + assertEquals(Collections.singletonList(expectedEntry), actualEntries); } @Test @@ -167,7 +167,7 @@ public void testKeyWords() throws IOException { BibEntry expectedEntry = new BibEntry(); expectedEntry.setField("keywords", "Female, Male"); - Assert.assertEquals(Collections.singletonList(expectedEntry), actualEntries); + assertEquals(Collections.singletonList(expectedEntry), actualEntries); } } @@ -183,19 +183,19 @@ public void testAllArticleTypes() throws IOException { BibEntry expectedEntry = new BibEntry(); expectedEntry.setType("article"); - expectedEntry.setField("keywords", "Female") - Assert.assertEquals(Collections.singletonList(expectedEntry), actualEntries); + expectedEntry.setField("keywords", "Female"); + assertEquals(Collections.singletonList(expectedEntry), actualEntries); } } @Test public void testGetFormatName() { - Assert.assertEquals("MedlinePlain", importer.getFormatName()); + assertEquals("MedlinePlain", importer.getFormatName()); } @Test public void testGetCLIId() { - Assert.assertEquals("medlineplain", importer.getId()); + assertEquals("medlineplain", importer.getId()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java index eb19a36992e3..3e8d1e6d3501 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java @@ -11,12 +11,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.model.entry.BibEntry; - -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index 59c411b4ed3e..5c0c66f8d570 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -12,8 +12,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index 1e3f1c662ff5..ae3bfd840815 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -1,7 +1,10 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; @@ -10,6 +13,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java index 32e071e5fc49..508711c4bfda 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java @@ -1,14 +1,16 @@ package net.sf.jabref.importer.fileformat; import java.io.IOException; -import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.List; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index 079910b47f22..8d3b8082c037 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -11,8 +11,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java index 7358c0337b3a..40950ba27322 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java @@ -10,12 +10,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bibtex.BibtexEntryAssert; -import net.sf.jabref.model.entry.BibEntry; - -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryAssert.java b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryAssert.java index e68e68d92524..219fd0877348 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryAssert.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryAssert.java @@ -4,12 +4,15 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import java.util.List; -import net.sf.jabref.importer.OutputPrinterToNull; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.importer.fileformat.ImportFormat; @@ -27,7 +30,7 @@ public class BibEntryAssert { * @param resourceName the resource to read * @param entry the entry to compare with */ - public static void assertEquals(Class clazz, String resourceName, BibEntry entry) + public static void assertEquals(Class clazz, String resourceName, BibEntry entry) throws IOException { Assert.assertNotNull(clazz); Assert.assertNotNull(resourceName); @@ -45,7 +48,7 @@ public static void assertEquals(Class clazz, String resourceNa * @param resourceName the resource to read * @param asIsEntries a list containing a single entry to compare with */ - public static void assertEquals(Class clazz, String resourceName, List asIsEntries) + public static void assertEquals(Class clazz, String resourceName, List asIsEntries) throws IOException { Assert.assertNotNull(clazz); Assert.assertNotNull(resourceName); @@ -73,14 +76,14 @@ private static List getListFromInputStream(InputStream is) throws IOEx * @param actualEntries a list containing a single entry to compare with */ public static void assertEquals(InputStream expectedInputStream, List actualEntries) - throws UnsupportedEncodingException, IOException { + throws IOException { Assert.assertNotNull(expectedInputStream); Assert.assertNotNull(actualEntries); Assert.assertEquals(getListFromInputStream(expectedInputStream), actualEntries); } public static void assertEquals(List expectedEntries, InputStream actualInputStream) - throws UnsupportedEncodingException, IOException { + throws IOException { Assert.assertNotNull(actualInputStream); Assert.assertNotNull(expectedEntries); Assert.assertEquals(expectedEntries, getListFromInputStream(actualInputStream)); @@ -94,34 +97,43 @@ public static void assertEquals(List expectedEntries, InputStream actu * @param actual the entry to compare with */ public static void assertEquals(InputStream expected, BibEntry actual) - throws UnsupportedEncodingException, IOException { + throws IOException { assertEquals(expected, Collections.singletonList(actual)); } /** - * Compares two InputStreams. For each InputStream a list will be created. expectedIs is read directly, actualIs is filtered through importerForActualIs to convert to a list of BibEntries. + * Compares two InputStreams. For each InputStream a list will be created. expectedIs is read directly, actualIs is filtered through importFormat to convert to a list of BibEntries. * @param expectedIs A BibtexImporter InputStream. - * @param actualIs Your ImportFormat InputStream you want to compare with a BibtexImporter ImportStream. - * @param importerForActualIs The fileformat you want to use to convert the actualIs to the list of expected BibEntries + * @param fileToImport The path to the file to be imported. + * @param importFormat The fileformat you want to use to read the passed file to get the list of expected BibEntries * @throws IOException */ - public static void assertEquals(InputStream expectedIs, InputStream actualIs, ImportFormat importerForActualIs) + public static void assertEquals(InputStream expectedIs, Path fileToImport, ImportFormat importFormat) throws IOException { - List actualEntries = importerForActualIs.importEntries(actualIs, new OutputPrinterToNull()); - Assert.assertEquals(getListFromInputStream(expectedIs), actualEntries); + assertEquals(getListFromInputStream(expectedIs), fileToImport, importFormat); + } + + public static void assertEquals(InputStream expectedIs, URL fileToImport, ImportFormat importFormat) + throws URISyntaxException, IOException { + assertEquals(expectedIs, Paths.get(fileToImport.toURI()), importFormat); } /** * Compares a list of BibEntries to an InputStream. actualIs is filtered through importerForActualIs to convert to a list of BibEntries. - * @param expectedIs A BibtexImporter InputStream. - * @param actualIs Your ImportFormat InputStream you want to compare with a BibtexImporter ImportStream. - * @param importerForActualIs The fileformat you want to use to convert the actualIs to the list of expected BibEntries + * @param expected A BibtexImporter InputStream. + * @param fileToImport The path to the file to be imported. + * @param importFormat The fileformat you want to use to read the passed file to get the list of expected BibEntries * @throws IOException */ - public static void assertEquals(List expected, InputStream actualIs, ImportFormat importerForActualIs) + public static void assertEquals(List expected, Path fileToImport, ImportFormat importFormat) throws IOException { - List actualEntries = importerForActualIs.importEntries(actualIs, new OutputPrinterToNull()); + List actualEntries = importFormat.importDatabase(fileToImport, Charset.defaultCharset()) + .getDatabase().getEntries(); Assert.assertEquals(expected, actualEntries); } + public static void assertEquals(List expected, URL fileToImport, ImportFormat importFormat) + throws URISyntaxException, IOException { + assertEquals(expected, Paths.get(fileToImport.toURI()), importFormat); + } } From b3f9b121155ba49bf8dba323b724634fdd4f6952 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 24 May 2016 14:26:22 +0200 Subject: [PATCH 095/268] Fix #651: Improve parsing of author names containing braces (#1443) --- CHANGELOG.md | 1 + .../java/net/sf/jabref/model/entry/AuthorListParser.java | 2 +- src/test/java/net/sf/jabref/model/entry/AuthorListTest.java | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ff5fd6816f7..50e7db4baadb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#973](https://github.com/JabRef/jabref/issues/973): Add additional DOI field for English version of MS Office 2007 XML - Fixed [#1412](https://github.com/JabRef/jabref/issues/1412): Save action *protect terms* protects terms within words unecessarily - Fixed [#1420](https://github.com/JabRef/jabref/issues/1420): Auto downloader should respect file pattern and propose correct filename +- Fixed [#651](https://github.com/JabRef/jabref/issues/651): Improve parsing of author names containing braces ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java b/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java index 4528e054fb7b..281961577393 100644 --- a/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java +++ b/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java @@ -356,7 +356,7 @@ private int getToken() { if (c == '{') { bracesLevel++; } - if (firstLetterIsFound && (tokenAbbr < 0) && (bracesLevel == 0)) { + if (firstLetterIsFound && (tokenAbbr < 0) && (bracesLevel == 0 || c == '{')) { tokenAbbr = tokenEnd; } if ((c == '}') && (bracesLevel > 0)) { diff --git a/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java b/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java index 532fccfa4fab..859e2ce84a67 100644 --- a/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java +++ b/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java @@ -605,4 +605,10 @@ public void parseNameWithHyphenInLastName() throws Exception { Author expected = new Author("Firstname", "F.", null, "Bailey-Jones", null); Assert.assertEquals(new AuthorList(expected), AuthorList.parse("Firstname Bailey-Jones")); } + + @Test + public void parseNameWithBraces() throws Exception { + Author expected = new Author("H{e}lene", "H.", null, "Fiaux", null); + Assert.assertEquals(new AuthorList(expected), AuthorList.parse("H{e}lene Fiaux")); + } } From b3d22bff9a5344e92fce11e27e76e1be8d175010 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 24 May 2016 14:29:11 +0200 Subject: [PATCH 096/268] Remove unused imports --- .../net/sf/jabref/importer/fileformat/InspecImporter.java | 6 ------ .../net/sf/jabref/importer/fileformat/MedlineImporter.java | 3 --- .../jabref/importer/fileformat/SilverPlatterImporter.java | 6 ------ src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java | 7 +++++-- .../importer/ImportFormatReaderTestParameterless.java | 5 ----- .../net/sf/jabref/importer/fileformat/RISImporterTest.java | 3 --- 6 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java index 82c4c8ee1f32..f60bad7fe4e3 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java @@ -17,18 +17,12 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.AuthorList; -import net.sf.jabref.model.entry.BibEntry; - import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java index ac2eccdd78a4..4a27483d3cc1 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java @@ -19,9 +19,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.Objects; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java index 5ad24b7e242e..1a0b43573998 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java @@ -17,18 +17,12 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import net.sf.jabref.importer.ImportFormatReader; -import net.sf.jabref.importer.OutputPrinter; -import net.sf.jabref.model.entry.AuthorList; -import net.sf.jabref.model.entry.BibEntry; - import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java index 1b880075d149..91bfb3e90a14 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java @@ -17,8 +17,11 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; diff --git a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java b/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java index 5a9e0b01d481..9c8c8e859727 100644 --- a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java +++ b/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java @@ -8,11 +8,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import org.junit.Before; -import org.junit.Test; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java index 50a85c5843de..75a0f683acc9 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java @@ -9,9 +9,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; From b1914807cf0f8377dc3a92f8ee3906f3c12032c2 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 24 May 2016 16:08:32 +0200 Subject: [PATCH 097/268] Move Encoding from BasePanel to MetaData (#1411) * Move Encoding to MetaData * Use list of entries instead of database in ArgumentProcessor * Remove unused imports * Fix compile error --- src/main/java/net/sf/jabref/MetaData.java | 14 ++++++++++ .../net/sf/jabref/cli/ArgumentProcessor.java | 13 ++++----- .../net/sf/jabref/collab/ChangeScanner.java | 2 +- .../sf/jabref/exporter/AutoSaveManager.java | 2 +- .../net/sf/jabref/exporter/ExportFormats.java | 4 ++- .../exporter/ExportToClipboardAction.java | 6 +++-- .../jabref/exporter/SaveDatabaseAction.java | 7 ++--- .../java/net/sf/jabref/gui/BasePanel.java | 16 ++--------- .../sf/jabref/gui/ImportInspectionDialog.java | 2 +- .../java/net/sf/jabref/gui/JabRefFrame.java | 27 +++++++------------ .../jabref/gui/actions/NewDatabaseAction.java | 3 +-- .../gui/actions/NewSubDatabaseAction.java | 3 +-- .../DatabasePropertiesDialog.java | 6 ++--- .../importer/AutosaveStartupPrompter.java | 2 +- .../sf/jabref/importer/ImportMenuItem.java | 2 +- .../jabref/importer/OpenDatabaseAction.java | 4 +-- .../net/sf/jabref/importer/ParserResult.java | 20 -------------- .../importer/fileformat/ImportFormat.java | 2 +- .../jabref/logic/search/DatabaseSearcher.java | 11 +++----- .../jabref/sql/importer/DbImportAction.java | 3 +-- .../net/sf/jabref/BibDatabaseContextTest.java | 6 +++++ src/test/java/net/sf/jabref/MetaDataTest.java | 3 ++- .../importer/OpenDatabaseActionTest.java | 12 ++++----- .../importer/fileformat/BibtexParserTest.java | 2 +- .../logic/search/DatabaseSearcherTest.java | 27 +++++++++---------- 25 files changed, 87 insertions(+), 112 deletions(-) diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index b8eb006a768e..5d1377fe2004 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.io.Reader; import java.io.StringReader; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -69,6 +70,8 @@ public class MetaData implements Iterable { private DBStrings dbStrings = new DBStrings(); + private Charset encoding = Globals.prefs.getDefaultEncoding(); + /** * The MetaData object stores all meta data sets in Vectors. To ensure that @@ -439,4 +442,15 @@ public void clearSaveActions() { public void clearSaveOrderConfig() { remove(SAVE_ORDER_CONFIG); } + + /** + * Returns the encoding used during parsing. + */ + public Charset getEncoding() { + return encoding; + } + + public void setEncoding(Charset encoding) { + this.encoding = Objects.requireNonNull(encoding); + } } diff --git a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java index 32c7c29a413c..bc2abb09e9c2 100644 --- a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java @@ -160,15 +160,16 @@ private boolean exportMatches(List loaded) { String searchTerm = data[0].replace("\\$", " "); //enables blanks within the search term: //$ stands for a blank ParserResult pr = loaded.get(loaded.size() - 1); + BibDatabaseContext databaseContext = pr.getDatabaseContext(); BibDatabase dataBase = pr.getDatabase(); SearchQuery query = new SearchQuery(searchTerm, Globals.prefs.getBoolean(JabRefPreferences.SEARCH_CASE_SENSITIVE), Globals.prefs.getBoolean(JabRefPreferences.SEARCH_REG_EXP)); - BibDatabase newBase = new DatabaseSearcher(query, dataBase).getDatabaseFromMatches(); //newBase contains only match entries + List matches = new DatabaseSearcher(query, dataBase).getMatches(); - //export database - if (newBase.hasEntries()) { + //export matches + if (!matches.isEmpty()) { String formatName; //read in the export format, take default format if no format entered @@ -195,8 +196,7 @@ private boolean exportMatches(List loaded) { // We have an ExportFormat instance: try { System.out.println(Localization.lang("Exporting") + ": " + data[1]); - BibDatabaseContext databaseContext = new BibDatabaseContext(newBase, pr.getMetaData()); - format.performExport(databaseContext, data[1], pr.getEncoding(), newBase.getEntries()); + format.performExport(databaseContext, data[1], databaseContext.getMetaData().getEncoding(), matches); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[1] + "': " + ex.getMessage()); @@ -373,7 +373,8 @@ private void exportFile(List loaded, String[] data) { } else { // We have an ExportFormat instance: try { - format.performExport(pr.getDatabaseContext(), data[0], pr.getEncoding(), null); + format.performExport(pr.getDatabaseContext(), data[0], + pr.getDatabaseContext().getMetaData().getEncoding(), null); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[0] + "': " + ex.getMessage()); diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index 77c082a4553b..1f632e4b7d87 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -160,7 +160,7 @@ private void storeTempDatabase() { JabRefExecutorService.INSTANCE.execute(() -> { try { SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs).withMakeBackup(false) - .withEncoding(panel.getEncoding()); + .withEncoding(panel.getBibDatabaseContext().getMetaData().getEncoding()); Defaults defaults = new Defaults(BibDatabaseMode .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); diff --git a/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java b/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java index ce60e941ff03..08f5769d13cf 100644 --- a/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java +++ b/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java @@ -94,7 +94,7 @@ private static boolean autoSave(BasePanel panel) { try { SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs) .withMakeBackup(false) - .withEncoding(panel.getEncoding()); + .withEncoding(panel.getBibDatabaseContext().getMetaData().getEncoding()); BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); SaveSession ss = databaseWriter.saveDatabase(panel.getBibDatabaseContext(), prefs); diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormats.java b/src/main/java/net/sf/jabref/exporter/ExportFormats.java index c59762c53454..d0d7959183b4 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFormats.java +++ b/src/main/java/net/sf/jabref/exporter/ExportFormats.java @@ -228,7 +228,9 @@ public void actionPerformed(ActionEvent e) { public void run() { try { format.performExport(frame.getCurrentBasePanel().getBibDatabaseContext(), - finFile.getPath(), frame.getCurrentBasePanel().getEncoding(), finEntries); + finFile.getPath(), + frame.getCurrentBasePanel().getBibDatabaseContext().getMetaData().getEncoding(), + finEntries); } catch (Exception ex) { LOGGER.warn("Problem exporting", ex); if (ex.getMessage() == null) { diff --git a/src/main/java/net/sf/jabref/exporter/ExportToClipboardAction.java b/src/main/java/net/sf/jabref/exporter/ExportToClipboardAction.java index 15664d972c1e..b3585157b48f 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportToClipboardAction.java +++ b/src/main/java/net/sf/jabref/exporter/ExportToClipboardAction.java @@ -114,10 +114,12 @@ public void run() { List entries = panel.getSelectedEntries(); // Write to file: - format.performExport(panel.getBibDatabaseContext(), tmp.getPath(), panel.getEncoding(), entries); + format.performExport(panel.getBibDatabaseContext(), tmp.getPath(), + panel.getBibDatabaseContext().getMetaData().getEncoding(), entries); // Read the file and put the contents on the clipboard: StringBuilder sb = new StringBuilder(); - try (Reader reader = new InputStreamReader(new FileInputStream(tmp), panel.getEncoding())) { + try (Reader reader = new InputStreamReader(new FileInputStream(tmp), + panel.getBibDatabaseContext().getMetaData().getEncoding())) { int s; while ((s = reader.read()) != -1) { sb.append((char) s); diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java index f5ec6b6f6afe..41e4c4d201ae 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java @@ -129,7 +129,8 @@ public void run() { } // Save the database: - success = saveDatabase(panel.getBibDatabaseContext().getDatabaseFile(), false, panel.getEncoding()); + success = saveDatabase(panel.getBibDatabaseContext().getDatabaseFile(), false, + panel.getBibDatabaseContext().getMetaData().getEncoding()); Globals.fileUpdateMonitor.updateTimeStamp(panel.getFileMonitorHandle()); } else { @@ -245,7 +246,7 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset encoding) try { if (commit) { session.commit(file); - panel.setEncoding(encoding); // Make sure to remember which encoding we used. + panel.getBibDatabaseContext().getMetaData().setEncoding(encoding); // Make sure to remember which encoding we used. } else { session.cancel(); } @@ -257,7 +258,7 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset encoding) if (ans == JOptionPane.YES_OPTION) { session.setUseBackup(false); session.commit(file); - panel.setEncoding(encoding); + panel.getBibDatabaseContext().getMetaData().setEncoding(encoding); } else { commit = false; } diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 3eae0ea90e10..be34572625fa 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -180,8 +180,6 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe private boolean saving; private boolean updatedExternally; - private Charset encoding; - // AutoCompleter used in the search bar private AutoCompleter searchAutoCompleter; // The undo manager. @@ -222,12 +220,10 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe private final SearchBar searchBar; private ContentAutoCompleters autoCompleters; - public BasePanel(JabRefFrame frame, BibDatabaseContext bibDatabaseContext, Charset encoding) { + public BasePanel(JabRefFrame frame, BibDatabaseContext bibDatabaseContext) { Objects.requireNonNull(frame); - Objects.requireNonNull(encoding); Objects.requireNonNull(bibDatabaseContext); - this.encoding = encoding; this.bibDatabaseContext = bibDatabaseContext; this.sidePaneManager = frame.getSidePaneManager(); @@ -305,14 +301,6 @@ public JabRefFrame frame() { return frame; } - public Charset getEncoding() { - return encoding; - } - - public void setEncoding(Charset encoding) { - this.encoding = encoding; - } - public void output(String s) { frame.output(s); } @@ -1172,7 +1160,7 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset enc, if (commit) { session.commit(file); - this.encoding = enc; // Make sure to remember which encoding we used. + this.bibDatabaseContext.getMetaData().setEncoding(enc); // Make sure to remember which encoding we used. } else { session.cancel(); } diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 3bf8c1084e13..7f27f3b475de 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -700,7 +700,7 @@ private void addSelectedEntries(NamedCompound ce, final List selected) // Create a new BasePanel for the entries: Defaults defaults = new Defaults(BibDatabaseMode .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); - panel = new BasePanel(frame, new BibDatabaseContext(defaults), Globals.prefs.getDefaultEncoding()); + panel = new BasePanel(frame, new BibDatabaseContext(defaults)); } boolean groupingCanceled = false; diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 4e6d0555a639..72b787f96d82 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -31,7 +31,6 @@ import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -1381,13 +1380,13 @@ public void addParserResult(ParserResult pr, boolean raisePanel) { BasePanel panel = getCurrentBasePanel(); if (panel == null) { // There is no open tab to add to, so we create a new tab: - addTab(pr.getDatabaseContext(), pr.getEncoding(), raisePanel); + addTab(pr.getDatabaseContext(), raisePanel); } else { List entries = new ArrayList<>(pr.getDatabase().getEntries()); addImportedEntries(panel, entries, false); } } else { - addTab(pr.getDatabaseContext(), pr.getEncoding(), raisePanel); + addTab(pr.getDatabaseContext(), raisePanel); } } @@ -1580,21 +1579,6 @@ public void setupAllTables() { } } - public BasePanel addTab(BibDatabaseContext databaseContext, Charset encoding, boolean raisePanel) { - Objects.requireNonNull(databaseContext); - - Charset usedEncoding; - if (encoding == null) { - usedEncoding = Globals.prefs.getDefaultEncoding(); - } else { - usedEncoding = encoding; - } - - BasePanel bp = new BasePanel(JabRefFrame.this, databaseContext, usedEncoding); - addTab(bp, raisePanel); - return bp; - } - private List collectDatabaseFilePaths() { List dbPaths = new ArrayList<>(getBasePanelCount()); @@ -1649,6 +1633,13 @@ public void addTab(BasePanel bp, boolean raisePanel) { } } + public BasePanel addTab(BibDatabaseContext databaseContext, boolean raisePanel) { + Objects.requireNonNull(databaseContext); + BasePanel bp = new BasePanel(JabRefFrame.this, databaseContext); + addTab(bp, raisePanel); + return bp; + } + /** * Creates icons for the disabled state for all JMenuItems with FontBasedIcons in the given menuElement. * This is necessary as Swing is not able to generate default disabled icons for font based icons. diff --git a/src/main/java/net/sf/jabref/gui/actions/NewDatabaseAction.java b/src/main/java/net/sf/jabref/gui/actions/NewDatabaseAction.java index 583d932c00e5..8b9b8f2edd28 100644 --- a/src/main/java/net/sf/jabref/gui/actions/NewDatabaseAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/NewDatabaseAction.java @@ -6,7 +6,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; -import net.sf.jabref.Globals; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.logic.l10n.Localization; @@ -33,7 +32,7 @@ public void actionPerformed(ActionEvent e) { // Create a new, empty, database. BibDatabaseContext bibDatabaseContext = new BibDatabaseContext(new Defaults(BibDatabaseMode.BIBTEX)); bibDatabaseContext.setMode(mode); - jabRefFrame.addTab(bibDatabaseContext, Globals.prefs.getDefaultEncoding(), true); + jabRefFrame.addTab(bibDatabaseContext, true); jabRefFrame.output(Localization.lang("New %0 database created.", mode.getFormattedName())); } } diff --git a/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java b/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java index 28e3e5bd07b0..a8702734f49c 100644 --- a/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java @@ -41,8 +41,7 @@ public void actionPerformed(ActionEvent e) { if (dialog.generatePressed()) { Defaults defaults = new Defaults( BibDatabaseMode.fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); - BasePanel bp = new BasePanel(jabRefFrame, new BibDatabaseContext(dialog.getGenerateDB(), defaults), - Globals.prefs.getDefaultEncoding()); // meta data + BasePanel bp = new BasePanel(jabRefFrame, new BibDatabaseContext(dialog.getGenerateDB(), defaults)); jabRefFrame.addTab(bp, true); jabRefFrame.output(Localization.lang("New database created.")); } diff --git a/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java b/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java index a5881cc73c1f..c96900b7bd36 100644 --- a/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java +++ b/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java @@ -186,7 +186,7 @@ public void setVisible(boolean visible) { } private void setValues() { - encoding.setSelectedItem(panel.getEncoding()); + encoding.setSelectedItem(panel.getBibDatabaseContext().getMetaData().getEncoding()); Optional storedSaveOrderConfig = metaData.getSaveOrderConfig(); boolean selected; @@ -231,9 +231,9 @@ private void setValues() { private void storeSettings() { - Charset oldEncoding = panel.getEncoding(); + Charset oldEncoding = panel.getBibDatabaseContext().getMetaData().getEncoding(); Charset newEncoding = (Charset) encoding.getSelectedItem(); - panel.setEncoding(newEncoding); + panel.getBibDatabaseContext().getMetaData().setEncoding(newEncoding); String text = fileDir.getText().trim(); if (text.isEmpty()) { diff --git a/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java b/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java index baad2d04eddc..e3c678fc365b 100644 --- a/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java +++ b/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java @@ -78,7 +78,7 @@ public void run() { loaded.add(pr); BibDatabaseContext databaseContext = pr.getDatabaseContext(); databaseContext.setDatabaseFile(file); - BasePanel panel = frame.addTab(databaseContext, pr.getEncoding(), first); + BasePanel panel = frame.addTab(databaseContext, first); location.put(pr, frame.getBasePanelCount() - 1); if (tryingAutosave) { panel.markNonUndoableBaseChanged(); diff --git a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java index 3956f8d67b99..7d3d0483ce29 100644 --- a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java +++ b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java @@ -194,7 +194,7 @@ public void update() { } } else { if (openInNew) { - frame.addTab(bibtexResult.getDatabaseContext(), Globals.prefs.getDefaultEncoding(), true); + frame.addTab(bibtexResult.getDatabaseContext(), true); frame.output( Localization.lang("Imported entries") + ": " + bibtexResult.getDatabase().getEntryCount()); } else { diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index b485c9832c7d..d894601bb114 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -309,7 +309,7 @@ public static void performPostOpenActions(BasePanel panel, ParserResult result, } } - public BasePanel addNewDatabase(ParserResult result, final File file, boolean raisePanel) { + private BasePanel addNewDatabase(ParserResult result, final File file, boolean raisePanel) { String fileName = file.getPath(); BibDatabase database = result.getDatabase(); @@ -320,7 +320,7 @@ public BasePanel addNewDatabase(ParserResult result, final File file, boolean ra } Defaults defaults = new Defaults(BibDatabaseMode.fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); - BasePanel basePanel = new BasePanel(frame, new BibDatabaseContext(database, meta, file, defaults), result.getEncoding()); + BasePanel basePanel = new BasePanel(frame, new BibDatabaseContext(database, meta, file, defaults)); // file is set to null inside the EventDispatcherThread SwingUtilities.invokeLater(() -> frame.addTab(basePanel, raisePanel)); diff --git a/src/main/java/net/sf/jabref/importer/ParserResult.java b/src/main/java/net/sf/jabref/importer/ParserResult.java index f0b165a0d6d9..0841a087e5ac 100644 --- a/src/main/java/net/sf/jabref/importer/ParserResult.java +++ b/src/main/java/net/sf/jabref/importer/ParserResult.java @@ -16,7 +16,6 @@ package net.sf.jabref.importer; import java.io.File; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -43,8 +42,6 @@ public class ParserResult { private final List duplicateKeys = new ArrayList<>(); private String errorMessage; - // Which encoding was used? - private Charset encoding; private boolean postponedAutosaveFound; private boolean invalid; @@ -107,23 +104,6 @@ public void setFile(File f) { file = f; } - /** - * Sets the variable indicating which encoding was used during parsing. - * - * @param enc the encoding. - */ - public void setEncoding(Charset enc) { - encoding = enc; - } - - /** - * Returns the encoding used during parsing, or null if not specified (indicates that - * prefs.get(JabRefPreferences.DEFAULT_ENCODING) was used). - */ - public Charset getEncoding() { - return encoding; - } - /** * Add a parser warning. * diff --git a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java index 0c4887630bf4..41f418328f8a 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java @@ -88,7 +88,7 @@ public boolean isRecognizedFormat(Path filePath, Charset encoding) throws IOExce public ParserResult importDatabase(Path filePath, Charset encoding) throws IOException { try (BufferedReader bufferedReader = getReader(filePath, encoding)) { ParserResult parserResult = importDatabase(bufferedReader); - parserResult.setEncoding(encoding); + parserResult.getMetaData().setEncoding(encoding); parserResult.setFile(filePath.toFile()); return parserResult; } diff --git a/src/main/java/net/sf/jabref/logic/search/DatabaseSearcher.java b/src/main/java/net/sf/jabref/logic/search/DatabaseSearcher.java index ac8242ead5bb..63d0cba0723a 100644 --- a/src/main/java/net/sf/jabref/logic/search/DatabaseSearcher.java +++ b/src/main/java/net/sf/jabref/logic/search/DatabaseSearcher.java @@ -42,21 +42,16 @@ public DatabaseSearcher(SearchQuery query, BibDatabase database) { this.database = Objects.requireNonNull(database); } - /** - * - * @return BibDatabase, never null - */ - public BibDatabase getDatabaseFromMatches() { + public List getMatches() { LOGGER.debug("Search term: " + query); if (!query.isValid()) { LOGGER.warn("Search failed: illegal search expression"); - return BibDatabases.createDatabase(Collections.emptyList()); + return Collections.emptyList(); } List matchEntries = database.getEntries().stream().filter(query::isMatch).collect(Collectors.toList()); - - return BibDatabases.createDatabase(BibDatabases.purgeEmptyEntries(matchEntries)); + return BibDatabases.purgeEmptyEntries(matchEntries); } } diff --git a/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java b/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java index 80ce9fd14d60..230c07961082 100644 --- a/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java +++ b/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java @@ -27,7 +27,6 @@ import javax.swing.JOptionPane; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.MnemonicAwareAction; @@ -190,7 +189,7 @@ public void update() { for (DBImporterResult res : databases) { databaseContext = res.getDatabaseContext(); if (databaseContext != null) { - BasePanel pan = frame.addTab(databaseContext, Globals.prefs.getDefaultEncoding(), true); + BasePanel pan = frame.addTab(databaseContext, true); pan.getBibDatabaseContext().getMetaData().setDBStrings(dbs); frame.setTabTitle(pan, res.getName() + "(Imported)", "Imported DB"); pan.markBaseChanged(); diff --git a/src/test/java/net/sf/jabref/BibDatabaseContextTest.java b/src/test/java/net/sf/jabref/BibDatabaseContextTest.java index df40d64b4d3c..e875a58a86f0 100644 --- a/src/test/java/net/sf/jabref/BibDatabaseContextTest.java +++ b/src/test/java/net/sf/jabref/BibDatabaseContextTest.java @@ -3,12 +3,18 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; public class BibDatabaseContextTest { + @Before + public void setUp() throws Exception { + Globals.prefs = JabRefPreferences.getInstance(); + } + @Test public void testTypeBasedOnDefaultBibtex() { BibDatabaseContext bibDatabaseContext = new BibDatabaseContext(new BibDatabase(), new MetaData(), new Defaults(BibDatabaseMode.BIBTEX)); diff --git a/src/test/java/net/sf/jabref/MetaDataTest.java b/src/test/java/net/sf/jabref/MetaDataTest.java index 9dc06d6c995f..514e87216695 100644 --- a/src/test/java/net/sf/jabref/MetaDataTest.java +++ b/src/test/java/net/sf/jabref/MetaDataTest.java @@ -20,6 +20,7 @@ public class MetaDataTest { @Before public void setUp() { + Globals.prefs = JabRefPreferences.getInstance(); metaData = new MetaData(); } @@ -39,4 +40,4 @@ public void serializeSingleSaveAction() throws IOException { "enabled;" + Globals.NEWLINE + "title[lower_case]" + Globals.NEWLINE + ";"); assertEquals(expectedSerialization, metaData.serialize()); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java b/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java index e8f4dd56952b..2fb9f4a729bb 100644 --- a/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java +++ b/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java @@ -46,25 +46,25 @@ public static void setUpGlobalsPrefs() { @Test public void useFallbackEncodingIfNoHeader() throws IOException { ParserResult result = OpenDatabaseAction.loadDatabase(bibNoHeader, defaultEncoding); - Assert.assertEquals(defaultEncoding, result.getEncoding()); + Assert.assertEquals(defaultEncoding, result.getMetaData().getEncoding()); } @Test public void useFallbackEncodingIfUnknownHeader() throws IOException { ParserResult result = OpenDatabaseAction.loadDatabase(bibWrongHeader, defaultEncoding); - Assert.assertEquals(defaultEncoding, result.getEncoding()); + Assert.assertEquals(defaultEncoding, result.getMetaData().getEncoding()); } @Test public void useSpecifiedEncoding() throws IOException { ParserResult result = OpenDatabaseAction.loadDatabase(bibHeader, StandardCharsets.US_ASCII); - Assert.assertEquals(StandardCharsets.UTF_8, result.getEncoding()); + Assert.assertEquals(StandardCharsets.UTF_8, result.getMetaData().getEncoding()); } @Test public void useSpecifiedEncodingWithSignature() throws IOException { ParserResult result = OpenDatabaseAction.loadDatabase(bibHeaderAndSignature, StandardCharsets.US_ASCII); - Assert.assertEquals(StandardCharsets.UTF_8, result.getEncoding()); + Assert.assertEquals(StandardCharsets.UTF_8, result.getMetaData().getEncoding()); } @Test @@ -103,7 +103,7 @@ public void entriesAreParsedHeaderAndSignature() throws IOException { @Test public void correctlyParseEncodingWithoutNewline() throws IOException { ParserResult result = OpenDatabaseAction.loadDatabase(bibEncodingWithoutNewline, defaultEncoding); - Assert.assertEquals(StandardCharsets.US_ASCII, result.getEncoding()); + Assert.assertEquals(StandardCharsets.US_ASCII, result.getMetaData().getEncoding()); BibDatabase db = result.getDatabase(); Assert.assertEquals("testPreamble", db.getPreamble()); @@ -114,4 +114,4 @@ public void correctlyParseEncodingWithoutNewline() throws IOException { BibEntry entry = entries.iterator().next(); Assert.assertEquals("testArticle", entry.getCiteKey()); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java index 450259deb976..fc2e8a76fed7 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java @@ -452,7 +452,7 @@ public void parseRecognizesHeaderButIgnoresEncoding() throws IOException { + " url = {http://james.howison.name/publications.html}" + "\n" + "}))")); - assertNull(result.getEncoding()); + assertEquals(Globals.prefs.getDefaultEncoding(), result.getMetaData().getEncoding()); Collection c = result.getDatabase().getEntries(); assertEquals(1, c.size()); diff --git a/src/test/java/net/sf/jabref/logic/search/DatabaseSearcherTest.java b/src/test/java/net/sf/jabref/logic/search/DatabaseSearcherTest.java index 5086415c0e92..bf3a96f40159 100644 --- a/src/test/java/net/sf/jabref/logic/search/DatabaseSearcherTest.java +++ b/src/test/java/net/sf/jabref/logic/search/DatabaseSearcherTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.search; import java.util.Collections; +import java.util.List; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; @@ -17,25 +18,23 @@ public class DatabaseSearcherTest { @Test public void testGetDatabaseFromMatchesEmptyDatabase() { BibDatabase database = new BibDatabase(); - BibDatabase newDatabase = new DatabaseSearcher(new SearchQuery("whatever", true, true), database) - .getDatabaseFromMatches(); - assertEquals(Collections.emptyList(), newDatabase.getEntries()); + List matches = new DatabaseSearcher(new SearchQuery("whatever", true, true), database).getMatches(); + assertEquals(Collections.emptyList(), matches); } @Test public void testGetDatabaseFromMatchesEmptyDatabaseInvalidSearchExpression() { BibDatabase database = new BibDatabase(); - BibDatabase newDatabase = new DatabaseSearcher(INVALID_SEARCH_QUERY, database).getDatabaseFromMatches(); - assertEquals(Collections.emptyList(), newDatabase.getEntries()); + List matches = new DatabaseSearcher(INVALID_SEARCH_QUERY, database).getMatches(); + assertEquals(Collections.emptyList(), matches); } @Test public void testGetDatabaseFromMatchesDatabaseWithEmptyEntries() { BibDatabase database = new BibDatabase(); database.insertEntry(new BibEntry()); - BibDatabase newDatabase = new DatabaseSearcher(new SearchQuery("whatever", true, true), database) - .getDatabaseFromMatches(); - assertEquals(Collections.emptyList(), newDatabase.getEntries()); + List matches = new DatabaseSearcher(new SearchQuery("whatever", true, true), database).getMatches(); + assertEquals(Collections.emptyList(), matches); } @Test @@ -45,9 +44,8 @@ public void testGetDatabaseFromMatchesDatabaseWithEntries() { entry.setType("article"); entry.setField("author", "harrer"); database.insertEntry(entry); - BibDatabase newDatabase = new DatabaseSearcher(new SearchQuery("whatever", true, true), database) - .getDatabaseFromMatches(); - assertEquals(Collections.emptyList(), newDatabase.getEntries()); + List matches = new DatabaseSearcher(new SearchQuery("whatever", true, true), database).getMatches(); + assertEquals(Collections.emptyList(), matches); } @Test @@ -57,8 +55,7 @@ public void testGetDatabaseFromMatchesDatabaseWithEntriesWithCorrectMatch() { entry.setType("article"); entry.setField("author", "harrer"); database.insertEntry(entry); - BibDatabase newDatabase = new DatabaseSearcher(new SearchQuery("harrer", true, true), database) - .getDatabaseFromMatches(); - assertEquals(Collections.singletonList(entry), newDatabase.getEntries()); + List matches = new DatabaseSearcher(new SearchQuery("harrer", true, true), database).getMatches(); + assertEquals(Collections.singletonList(entry), matches); } -} \ No newline at end of file +} From fd81b71f665de02341de43aae512664219fd1dea Mon Sep 17 00:00:00 2001 From: Braunch Date: Tue, 24 May 2016 16:31:54 +0200 Subject: [PATCH 098/268] Scrollingthroughentrylisttest (#1361) * Create UI-test for scrolling through the entry table * abstract the integration tests a bit more * enhance scrolling through the list test --- .../net/sf/jabref/gui/AbstractUITest.java | 108 ++++++++++++++++++ .../net/sf/jabref/gui/EntryTableTest.java | 64 +++++++++++ .../java/net/sf/jabref/gui/GUITest.java | 104 +++++------------ .../java/net/sf/jabref/gui/UndoTest.java | 55 +-------- 4 files changed, 204 insertions(+), 127 deletions(-) create mode 100644 src/integrationTest/java/net/sf/jabref/gui/AbstractUITest.java create mode 100644 src/integrationTest/java/net/sf/jabref/gui/EntryTableTest.java diff --git a/src/integrationTest/java/net/sf/jabref/gui/AbstractUITest.java b/src/integrationTest/java/net/sf/jabref/gui/AbstractUITest.java new file mode 100644 index 000000000000..087b49f12b9d --- /dev/null +++ b/src/integrationTest/java/net/sf/jabref/gui/AbstractUITest.java @@ -0,0 +1,108 @@ +package net.sf.jabref.gui; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import net.sf.jabref.JabRefMain; + +import org.assertj.swing.fixture.AbstractWindowFixture; +import org.assertj.swing.fixture.FrameFixture; +import org.assertj.swing.fixture.JFileChooserFixture; +import org.assertj.swing.fixture.JTableFixture; +import org.assertj.swing.image.ScreenshotTaker; +import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase; +import org.assertj.swing.timing.Pause; +import org.junit.Assert; + +import static org.assertj.swing.finder.WindowFinder.findFrame; +import static org.assertj.swing.launcher.ApplicationLauncher.application; + +public abstract class AbstractUITest extends AssertJSwingJUnitTestCase { + + protected final static int SPEED_NORMAL = 50; + + protected AWTExceptionHandler awtExceptionHandler; + protected FrameFixture mainFrame; + + @Override + protected void onSetUp() { + awtExceptionHandler = new AWTExceptionHandler(); + awtExceptionHandler.installExceptionDetectionInEDT(); + application(JabRefMain.class).start(); + + robot().waitForIdle(); + + robot().settings().timeoutToFindSubMenu(1_000); + robot().settings().delayBetweenEvents(SPEED_NORMAL); + + mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); + robot().waitForIdle(); + } + + /** + * Returns the absolute Path of the given relative Path + * The backlashes are replaced with forwardslashes b/c assertJ can't type the former one on windows + * @param relativePath the relative path to the resource database + */ + protected String getAbsolutePath(String relativePath) { + final URL resource = this.getClass().getClassLoader().getResource(relativePath); + try { + return Paths.get(resource.toURI()).toAbsolutePath().toString().replace("\\", "/"); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + return null; + } + + /** + * opens a database and gives JabRef a second to open it before proceeding + */ + protected void importBibIntoNewDatabase(String path) { + mainFrame.menuItemWithPath("File", "Import into new database").click(); + JFileChooserFixture openFileDialog = mainFrame.fileChooser(); + robot().settings().delayBetweenEvents(1); + openFileDialog.fileNameTextBox().enterText(path); + openFileDialog.approve(); + Pause.pause(1_000); + } + + protected void exitJabRef() { + mainFrame.menuItemWithPath("File", "Quit").click(); + awtExceptionHandler.assertNoExceptions(); + } + + protected void newDatabase() { + mainFrame.menuItemWithPath("File", "New BibTeX database").click(); + } + + protected void closeDatabase() { + mainFrame.menuItemWithPath("File", "Close database").click(); + } + + protected void takeScreenshot(AbstractWindowFixture dialog, String filename) throws IOException { + ScreenshotTaker screenshotTaker = new ScreenshotTaker(); + Path folder = Paths.get("build", "screenshots"); + // Create build/srceenshots folder if not present + if (!Files.exists(folder)) { + Files.createDirectory(folder); + } + Path file = folder.resolve(filename + ".png").toAbsolutePath(); + // Delete already present file + if (Files.exists(file)) { + Files.delete(file); + } + screenshotTaker.saveComponentAsPng(dialog.target(), file.toString()); + } + + protected void assertColumnValue(JTableFixture table, int rowIndex, int columnIndex, String selectionValue){ + String[][] tableContent; + tableContent = table.contents(); + + String value = tableContent[rowIndex][columnIndex]; + Assert.assertEquals(value, selectionValue); + } +} diff --git a/src/integrationTest/java/net/sf/jabref/gui/EntryTableTest.java b/src/integrationTest/java/net/sf/jabref/gui/EntryTableTest.java new file mode 100644 index 000000000000..3b7b6c7c0d66 --- /dev/null +++ b/src/integrationTest/java/net/sf/jabref/gui/EntryTableTest.java @@ -0,0 +1,64 @@ +package net.sf.jabref.gui; + +import java.awt.event.KeyEvent; +import java.util.regex.Pattern; + +import org.assertj.swing.fixture.JTableCellFixture; +import org.assertj.swing.fixture.JTableFixture; +import org.junit.Assert; +import org.junit.Test; + +/** + * Specific Use-Case: + * I import a database. Then I doubleclick on the first entry in the table to open the entry editor. + * Then I click on the first entry again, and scroll through all of the lists entries, without having to click + * on the table again. + */ +public class EntryTableTest extends AbstractUITest{ + + private final static int SCROLL_ACTION_EXECUTION = 5; + private final static String TEST_FILE_NAME = "testbib/testjabref.bib"; + private final static int DOWN = KeyEvent.VK_DOWN; + private final static int UP = KeyEvent.VK_UP; + private final static int TITLE_COLUMN_INDEX = 5; + + @Test + public void scrollThroughEntryList() { + String path = getAbsolutePath(TEST_FILE_NAME); + + importBibIntoNewDatabase(path); + + JTableFixture entryTable = mainFrame.table(); + + //use a pattern from the first row to select it since it seems to be the best way to get the cell object + Pattern pattern = Pattern.compile("256.*"); + JTableCellFixture firstCell = entryTable.cell(pattern); + + entryTable.selectRows(0).doubleClick(); + //delay has to be shortened so that double click is recognized + robot().settings().delayBetweenEvents(0); + firstCell.doubleClick(); + robot().settings().delayBetweenEvents(SPEED_NORMAL); + + firstCell.click(); + //is the first table entry selected? + assertColumnValue(entryTable, 0, TITLE_COLUMN_INDEX, entryTable.selectionValue()); + + //go throught the table and check if the entry with the correct index is selected + for (int i=0; i < SCROLL_ACTION_EXECUTION; i++) { + robot().pressAndReleaseKey(DOWN); + Assert.assertTrue(entryTable.selectionValue() != null); + assertColumnValue(entryTable, i+1, TITLE_COLUMN_INDEX, entryTable.selectionValue()); + } + //do the same going up again + for (int i = SCROLL_ACTION_EXECUTION; i > 0; i--) { + robot().pressAndReleaseKey(UP); + Assert.assertTrue(entryTable.selectionValue() != null); + assertColumnValue(entryTable, i-1, TITLE_COLUMN_INDEX, entryTable.selectionValue()); + } + + closeDatabase(); + exitJabRef(); + } + +} diff --git a/src/integrationTest/java/net/sf/jabref/gui/GUITest.java b/src/integrationTest/java/net/sf/jabref/gui/GUITest.java index 71d2273b5a1f..0416a9afbdf4 100644 --- a/src/integrationTest/java/net/sf/jabref/gui/GUITest.java +++ b/src/integrationTest/java/net/sf/jabref/gui/GUITest.java @@ -1,94 +1,52 @@ package net.sf.jabref.gui; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import javax.swing.JButton; -import net.sf.jabref.JabRefMain; import net.sf.jabref.gui.dbproperties.DatabasePropertiesDialog; import net.sf.jabref.gui.preftabs.PreferencesDialog; import org.assertj.swing.core.GenericTypeMatcher; import org.assertj.swing.dependency.jsr305.Nonnull; -import org.assertj.swing.fixture.AbstractWindowFixture; import org.assertj.swing.fixture.DialogFixture; -import org.assertj.swing.fixture.FrameFixture; -import org.assertj.swing.image.ScreenshotTaker; -import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase; -import org.assertj.swing.timing.Pause; import org.junit.Ignore; import org.junit.Test; import static org.assertj.swing.finder.WindowFinder.findDialog; -import static org.assertj.swing.finder.WindowFinder.findFrame; -import static org.assertj.swing.launcher.ApplicationLauncher.application; -public class GUITest extends AssertJSwingJUnitTestCase { - private AWTExceptionHandler awtExceptionHandler; - - @Override - protected void onSetUp() { - awtExceptionHandler = new AWTExceptionHandler(); - awtExceptionHandler.installExceptionDetectionInEDT(); - application(JabRefMain.class).start(); - - robot().waitForIdle(); - - robot().settings().timeoutToFindSubMenu(1_000); - robot().settings().delayBetweenEvents(50); - } +public class GUITest extends AbstractUITest { @Test public void testExit() { - FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); - Pause.pause(1_000); - exitJabRef(mainFrame); - } - - private void exitJabRef(FrameFixture mainFrame) { - mainFrame.menuItemWithPath("File", "Quit").click(); - awtExceptionHandler.assertNoExceptions(); + exitJabRef(); } @Test public void testNewFile() { - FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); - newDatabase(mainFrame); - - mainFrame.menuItemWithPath("File", "Close database").click(); - exitJabRef(mainFrame); - } - - private void newDatabase(FrameFixture mainFrame) { - mainFrame.menuItemWithPath("File", "New BibTeX database").click(); + newDatabase(); + closeDatabase(); + exitJabRef(); } @Test public void testCreateBibtexEntry() throws IOException { - FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); - - newDatabase(mainFrame); + newDatabase(); mainFrame.menuItemWithPath("BibTeX", "New entry...").click(); findDialog(EntryTypeDialog.class).withTimeout(10_000).using(robot()) .button(new GenericTypeMatcher(JButton.class) { - @Override protected boolean isMatching(@Nonnull JButton jButton) { return "Book".equals(jButton.getText()); } }).click(); takeScreenshot(mainFrame, "MainWindowWithOneDatabase"); - exitJabRef(mainFrame); } @Ignore @Test public void testOpenAndSavePreferences() throws IOException { - FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); mainFrame.menuItemWithPath("Options", "Preferences").click(); robot().waitForIdle(); @@ -96,41 +54,50 @@ public void testOpenAndSavePreferences() throws IOException { DialogFixture preferencesDialog = findDialog(PreferencesDialog.class).withTimeout(10_000).using(robot()); takeScreenshot(preferencesDialog, "PreferencesDialog"); preferencesDialog.button(new GenericTypeMatcher(JButton.class) { - @Override protected boolean isMatching(@Nonnull JButton jButton) { return "OK".equals(jButton.getText()); } }).click(); - exitJabRef(mainFrame); + exitJabRef(); } + /** + * tests different buttons + * sometimes this test clicks some buttons twice to reverse their effect and leaves JabRef as it was before + */ @Test public void testViewChanges() { - FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); - - newDatabase(mainFrame); + newDatabase(); mainFrame.menuItemWithPath("View", "Increase table font size").click(); mainFrame.menuItemWithPath("View", "Decrease table font size").click(); + mainFrame.menuItemWithPath("View", "Web search").click(); + mainFrame.menuItemWithPath("View", "Web search").click(); + mainFrame.menuItemWithPath("View", "Toggle groups interface").click(); + mainFrame.menuItemWithPath("View", "Toggle groups interface").click(); + mainFrame.menuItemWithPath("View", "Toggle entry preview").click(); + mainFrame.menuItemWithPath("View", "Toggle entry preview").click(); + + mainFrame.menuItemWithPath("View", "Switch preview layout").click(); mainFrame.menuItemWithPath("View", "Switch preview layout").click(); + + mainFrame.menuItemWithPath("View", "Hide/show toolbar").click(); mainFrame.menuItemWithPath("View", "Hide/show toolbar").click(); + mainFrame.menuItemWithPath("View", "Focus entry table").click(); - newDatabase(mainFrame); - mainFrame.menuItemWithPath("File", "Close database").click(); - exitJabRef(mainFrame); + closeDatabase(); + exitJabRef(); } @Test public void testDatabasePropertiesDialog() throws IOException { - - FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); - newDatabase(mainFrame); + newDatabase(); mainFrame.menuItemWithPath("File", "Database properties").click(); @@ -139,28 +106,13 @@ public void testDatabasePropertiesDialog() throws IOException { DialogFixture databasePropertiesDialog = findDialog(DatabasePropertiesDialog.class).withTimeout(10_000).using(robot()); takeScreenshot(databasePropertiesDialog, "DatabasePropertiesDialog"); databasePropertiesDialog.button(new GenericTypeMatcher(JButton.class) { - @Override protected boolean isMatching(@Nonnull JButton jButton) { return "OK".equals(jButton.getText()); } }).click(); - exitJabRef(mainFrame); - } - - private void takeScreenshot(AbstractWindowFixture dialog, String filename) throws IOException { - ScreenshotTaker screenshotTaker = new ScreenshotTaker(); - Path folder = Paths.get("build", "screenshots"); - // Create build/srceenshots folder if not present - if (!Files.exists(folder)) { - Files.createDirectory(folder); - } - Path file = folder.resolve(filename + ".png").toAbsolutePath(); - // Delete already present file - if (Files.exists(file)) { - Files.delete(file); - } - screenshotTaker.saveComponentAsPng(dialog.target(), file.toString()); + closeDatabase(); + exitJabRef(); } } diff --git a/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java b/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java index 06f57d2899c4..da10983e2d2f 100644 --- a/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java +++ b/src/integrationTest/java/net/sf/jabref/gui/UndoTest.java @@ -1,61 +1,15 @@ package net.sf.jabref.gui; -import java.io.File; - -import net.sf.jabref.JabRefMain; - -import org.assertj.swing.fixture.FrameFixture; -import org.assertj.swing.fixture.JFileChooserFixture; import org.assertj.swing.fixture.JTableFixture; -import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase; import org.junit.Test; -import static org.assertj.swing.finder.WindowFinder.findFrame; -import static org.assertj.swing.launcher.ApplicationLauncher.application; import static org.junit.Assert.assertTrue; -public class UndoTest extends AssertJSwingJUnitTestCase { - - private AWTExceptionHandler awtExceptionHandler; - - @Override - protected void onSetUp() { - awtExceptionHandler = new AWTExceptionHandler(); - awtExceptionHandler.installExceptionDetectionInEDT(); - application(JabRefMain.class).start(); - - robot().waitForIdle(); - - robot().settings().timeoutToFindSubMenu(1_000); - robot().settings().delayBetweenEvents(50); - } - - private void exitJabRef(FrameFixture mainFrame) { - mainFrame.menuItemWithPath("File", "Quit").click(); - awtExceptionHandler.assertNoExceptions(); - } - - private String getTestFilePath(String fileName) { - return new File(this.getClass().getClassLoader().getResource(fileName).getFile()).getAbsolutePath(); - } - - private void importBibIntoNewDatabase(FrameFixture mainFrame, String path) { - // have to replace backslashes with normal slashes b/c assertJ can't type the former one on windows - path = path.replace("\\", "/"); - - mainFrame.menuItemWithPath("File", "Import into new database").click(); - JFileChooserFixture openFileDialog = mainFrame.fileChooser(); - robot().settings().delayBetweenEvents(1); - openFileDialog.fileNameTextBox().enterText(path); - robot().settings().delayBetweenEvents(1_000); - openFileDialog.approve(); - robot().settings().delayBetweenEvents(50); - } +public class UndoTest extends AbstractUITest { @Test public void undoCutOfMultipleEntries() { - FrameFixture mainFrame = findFrame(JabRefFrame.class).withTimeout(10_000).using(robot()); - importBibIntoNewDatabase(mainFrame, getTestFilePath("testbib/testjabref.bib")); + importBibIntoNewDatabase(getAbsolutePath("testbib/testjabref.bib")); JTableFixture entryTable = mainFrame.table(); @@ -68,9 +22,8 @@ public void undoCutOfMultipleEntries() { mainFrame.menuItemWithPath("Edit", "Undo").click(); entryTable.requireRowCount(oldRowCount); - mainFrame.menuItemWithPath("File", "Close database").click(); - mainFrame.menuItemWithPath("File", "Close database").click(); - exitJabRef(mainFrame); + closeDatabase(); + exitJabRef(); } } From 2a979fde87f4f443444442e6e4f6b0d35d0af684 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 24 May 2016 17:41:26 +0200 Subject: [PATCH 099/268] Correctly initialize save actions if read from file --- src/main/java/net/sf/jabref/MetaData.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index 5d1377fe2004..669a8293b0b6 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -97,6 +97,10 @@ public MetaData(Map inData) throws ParseException { if (GROUPSTREE.equals(entry.getKey())) { putGroups(orderedData); // the keys "groupsversion" and "groups" were used in JabRef versions around 1.3, we will not use them here + } else if (SAVE_ACTIONS.equals(entry.getKey())) { + boolean enablementStatus = "enabled".equals(orderedData.get(0)); + String formatterString = orderedData.get(1); + setSaveActions(new FieldFormatterCleanups(enablementStatus, formatterString)); } else { putData(entry.getKey(), orderedData); } @@ -112,7 +116,7 @@ public MetaData() { public Optional getSaveOrderConfig() { List storedSaveOrderConfig = getData(SAVE_ORDER_CONFIG); - if(storedSaveOrderConfig != null) { + if (storedSaveOrderConfig != null) { return Optional.of(new SaveOrderConfig(storedSaveOrderConfig)); } return Optional.empty(); @@ -320,7 +324,7 @@ public boolean isProtected() { public List getContentSelectors(String fieldName) { List contentSelectors = getData(SELECTOR_META_PREFIX + fieldName); - if(contentSelectors == null) { + if (contentSelectors == null) { return Collections.emptyList(); } else { return contentSelectors; @@ -378,7 +382,7 @@ public Map serialize() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(Globals.NEWLINE); - for(String groupNode : groupsRoot.getTreeAsString()) { + for (String groupNode : groupsRoot.getTreeAsString()) { stringBuilder.append(StringUtil.quote(groupNode, ";", '\\')); stringBuilder.append(";"); stringBuilder.append(Globals.NEWLINE); From 6985fda86511f97907e8c96f322932163220a1e7 Mon Sep 17 00:00:00 2001 From: MLEP Date: Tue, 24 May 2016 21:29:05 +0200 Subject: [PATCH 100/268] French localization: translation of an empty string (#1448) --- src/main/resources/l10n/JabRef_fr.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 7fb665449433..23479f5c6eee 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1631,4 +1631,4 @@ Get_fulltext=Obtenir_le_document Download_from_URL=Télécharger_depuis_l'URL -Decryption_not_supported.= +Decryption_not_supported.=Déchiffrement_non_supporté. From 8b403fc631d2b07fb03d8fc8b776984aee7b2561 Mon Sep 17 00:00:00 2001 From: hakova Date: Tue, 24 May 2016 21:36:50 -0500 Subject: [PATCH 101/268] Updated jabref_tr.properties Translated the last three entries to Turkish --- src/main/resources/l10n/JabRef_tr.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 63b7b4fde802..157821211811 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1615,8 +1615,8 @@ Copied_version_to_clipboard=Sürüm_panoya_kopyalandı BibTeX_key=BibTeX_anahtarı Message=Mesaj -Get_fulltext= +Get_fulltext=Tammetni_getir -Download_from_URL= +Download_from_URL=URL'den_indir -Decryption_not_supported.= +Decryption_not_supported.=Şifre_çözme_desteklenmiyor. From 4a6f1915595e0bb5f5a0af558f434a10c618f6eb Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 25 May 2016 13:06:24 +0200 Subject: [PATCH 102/268] DOI improvements (#1447) * Fix #1420 Auto downloader should respect file pattern and propose correct filename * Improve DOI detection #1424 * Add tests * Resolves #1421 Auto downloader should try to retrieve DOI if not present and fetch afterwards * Add external library, document test class * Changelog --- CHANGELOG.md | 1 + build.gradle | 1 + external-libraries.txt | 5 ++ .../gui/entryeditor/FieldExtraComponents.java | 13 ++- .../sf/jabref/importer/fetcher/CrossRef.java | 52 +++++++++-- .../fetcher/CrossrefFetcherEvaluator.java | 86 +++++++++++++++++++ .../jabref/logic/fulltext/FindFullText.java | 12 ++- .../java/net/sf/jabref/logic/util/DOI.java | 13 +++ .../jabref/importer/fetcher/CrossRefTest.java | 19 +++- 9 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 50e7db4baadb..311d1100178f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1412](https://github.com/JabRef/jabref/issues/1412): Save action *protect terms* protects terms within words unecessarily - Fixed [#1420](https://github.com/JabRef/jabref/issues/1420): Auto downloader should respect file pattern and propose correct filename - Fixed [#651](https://github.com/JabRef/jabref/issues/651): Improve parsing of author names containing braces +- Fixed [#1421](https://github.com/JabRef/jabref/issues/1421):Auto downloader should try to retrieve DOI if not present and fetch afterwards ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/build.gradle b/build.gradle index 78ba85ff62f4..6d7558a6952c 100644 --- a/build.gradle +++ b/build.gradle @@ -104,6 +104,7 @@ dependencies { compile 'org.jsoup:jsoup:1.9.1' compile 'com.mashape.unirest:unirest-java:1.4.9' + compile 'info.debatty:java-string-similarity:0.13' compile 'org.apache.logging.log4j:log4j-jcl:2.5' compile 'org.apache.logging.log4j:log4j-api:2.5' diff --git a/external-libraries.txt b/external-libraries.txt index 287885624615..0d9eb61b217b 100644 --- a/external-libraries.txt +++ b/external-libraries.txt @@ -72,6 +72,11 @@ Project: Unirest for Java URL: https://github.com/Mashape/unirest-java License: MIT +Id: info.debatty:java-string-similarity +Project: Java String Similarity +URL: https://github.com/tdebatty/java-string-similarity +License: MIT + Id: mysql:mysql-connector-java Project: MySQL Connector/J URL: http://www.mysql.de/downloads/connector/j/ diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index 4148a8423a87..96d97966aca9 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -46,7 +46,6 @@ import net.sf.jabref.gui.fieldeditors.FieldEditor; import net.sf.jabref.gui.mergeentries.MergeEntryDOIDialog; import net.sf.jabref.gui.undo.UndoableFieldChange; -import net.sf.jabref.importer.fetcher.CrossRef; import net.sf.jabref.logic.journals.JournalAbbreviationRepository; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLUtil; @@ -187,12 +186,12 @@ public static Optional getDoiExtraComponent(BasePanel panel, EntryEd // lookup doi JButton doiButton = new JButton(Localization.lang("Lookup DOI")); doiButton.addActionListener(actionEvent -> { - Optional doi = CrossRef.findDOI(entryEditor.getEntry()); - if (doi.isPresent()) { - entryEditor.getEntry().setField("doi", doi.get().getDOI()); - } else { - panel.frame().setStatus(Localization.lang("No DOI found")); - } + Optional doi = DOI.fromBibEntry(entryEditor.getEntry()); + if (doi.isPresent()) { + entryEditor.getEntry().setField("doi", doi.get().getDOI()); + } else { + panel.frame().setStatus(Localization.lang("No DOI found")); + } }); // fetch bibtex data JButton fetchButton = new JButton(Localization.lang("Get BibTeX data from DOI")); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java index f6f30f627811..14fd6970b609 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java @@ -1,8 +1,10 @@ package net.sf.jabref.importer.fetcher; +import java.util.Locale; import java.util.Objects; import java.util.Optional; +import net.sf.jabref.logic.formatter.bibtexfields.RemoveBracesFormatter; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; @@ -10,19 +12,24 @@ import com.mashape.unirest.http.JsonNode; import com.mashape.unirest.http.Unirest; import com.mashape.unirest.http.exceptions.UnirestException; +import info.debatty.java.stringsimilarity.Levenshtein; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; /** * A class for fetching DOIs from CrossRef * - * @see https://github.com/CrossRef/rest-api-doc + * See https://github.com/CrossRef/rest-api-doc */ public class CrossRef { private static final Log LOGGER = LogFactory.getLog(CrossRef.class); private static final String API_URL = "http://api.crossref.org"; + private static final Levenshtein METRIC_DISTANCE = new Levenshtein(); + private static final int METRIC_THRESHOLD = 4; public static Optional findDOI(BibEntry entry) { Objects.requireNonNull(entry); @@ -44,10 +51,12 @@ public static Optional findDOI(BibEntry entry) { .asJson(); JSONArray items = response.getBody().getObject().getJSONObject("message").getJSONArray("items"); - String dataTitle = items.getJSONObject(0).getJSONArray("title").getString(0); - String dataDOI = items.getJSONObject(0).getString("DOI"); - LOGGER.info("DOI " + dataDOI + " for " + title + " found."); - return DOI.build(dataDOI); + // quality check + if (checkValidity(entry, items)) { + String dataDOI = items.getJSONObject(0).getString("DOI"); + LOGGER.debug("DOI " + dataDOI + " for " + title + " found."); + return DOI.build(dataDOI); + } } catch (UnirestException e) { LOGGER.warn("Unable to query CrossRef API: " + e.getMessage(), e); } @@ -70,4 +79,37 @@ private static String enhanceQuery(String query, BibEntry entry) { return enhancedQuery.toString(); } + + private static boolean checkValidity(BibEntry entry, JSONArray result) { + final String entryTitle = new RemoveBracesFormatter().format(entry.getField("title")); + + // currently only title-based + // title: [ "How the Mind Hurts and Heals the Body." ] + // subtitle: [ "" ] + try { + // title + JSONObject data = result.getJSONObject(0); + String dataTitle = data.getJSONArray("title").getString(0); + + if (editDistanceIgnoreCase(entryTitle, dataTitle) <= METRIC_THRESHOLD) { + return true; + } + + // subtitle + // additional check, as sometimes subtitle is needed but sometimes only duplicates the title + if (data.getJSONArray("subtitle").length() > 0) { + String dataWithSubTitle = dataTitle + " " + data.getJSONArray("subtitle").getString(0); + + return editDistanceIgnoreCase(entryTitle, dataWithSubTitle) <= METRIC_THRESHOLD; + } + + return false; + } catch(JSONException ex) { + return false; + } + } + + private static double editDistanceIgnoreCase(String a, String b) { + return METRIC_DISTANCE.distance(a.toLowerCase(Locale.ENGLISH), b.toLowerCase(Locale.ENGLISH)); + } } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java new file mode 100644 index 000000000000..b31fe6706980 --- /dev/null +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java @@ -0,0 +1,86 @@ +package net.sf.jabref.importer.fetcher; + +import java.io.FileReader; +import java.io.IOException; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.util.DOI; +import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.entry.BibEntry; + +/** + * Useful for checking out new algorithm improvements and thresholds. Not used inside the JabRef code itself. + */ +public class CrossrefFetcherEvaluator { + public static void main(String[] args) throws IOException, InterruptedException { + Globals.prefs = JabRefPreferences.getInstance(); + + BibtexParser parser = new BibtexParser(new FileReader(args[0])); + ParserResult result = parser.parse(); + BibDatabase db = result.getDatabase(); + + int total = result.getDatabase().getEntryCount(); + + AtomicInteger dois = new AtomicInteger(); + AtomicInteger doiFound = new AtomicInteger(); + AtomicInteger doiNew = new AtomicInteger(); + AtomicInteger doiIdentical = new AtomicInteger(); + + + List entries = db.getEntries(); + CountDownLatch countDownLatch = new CountDownLatch(entries.size()); + + ExecutorService executorService = Executors.newFixedThreadPool(5); + + for (BibEntry entry : entries) { + executorService.execute(new Runnable() { + + @Override + public void run() { + Optional origDOI = DOI.build(entry.getField("doi")); + if (origDOI.isPresent()) { + dois.incrementAndGet(); + Optional crossrefDOI = CrossRef.findDOI(entry); + if (crossrefDOI.isPresent()) { + doiFound.incrementAndGet(); + if (origDOI.get().getDOI().equalsIgnoreCase(crossrefDOI.get().getDOI())) { + doiIdentical.incrementAndGet(); + } else { + System.out.println("DOI not identical for : " + entry); + } + } else { + System.out.println("DOI not found for: " + entry); + } + } else { + Optional crossrefDOI = CrossRef.findDOI(entry); + if (crossrefDOI.isPresent()) { + System.out.println("New DOI found for: " + entry); + doiNew.incrementAndGet(); + } + } + countDownLatch.countDown(); + } + }); + + } + countDownLatch.await(); + + System.out.println("---------------------------------"); + System.out.println("Total DB size: " + total); + System.out.println("Total DOIs: " + dois); + System.out.println("DOIs found: " + doiFound); + System.out.println("DOIs identical: " + doiIdentical); + System.out.println("New DOIs found: " + doiNew); + + executorService.shutdown(); + } +} diff --git a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java index 06b393de3156..10bbe9be315a 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java @@ -6,7 +6,9 @@ import java.util.List; import java.util.Optional; +import net.sf.jabref.importer.fetcher.CrossRef; import net.sf.jabref.logic.io.MimeTypeDetector; +import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; import org.apache.commons.logging.Log; @@ -38,9 +40,17 @@ public FindFullText(List fetcher) { } public Optional findFullTextPDF(BibEntry entry) { + // for accuracy, fetch DOI first but do not modify entry + BibEntry clonedEntry = (BibEntry) entry.clone(); + String doi = clonedEntry.getField("doi"); + + if (doi == null || !DOI.build(doi).isPresent()) { + CrossRef.findDOI(clonedEntry).ifPresent(e -> clonedEntry.setField("doi", e.getDOI())); + } + for (FullTextFinder finder : finders) { try { - Optional result = finder.findFullText(entry); + Optional result = finder.findFullText(clonedEntry); if (result.isPresent() && MimeTypeDetector.isPdfContentType(result.get().toString())) { return result; diff --git a/src/main/java/net/sf/jabref/logic/util/DOI.java b/src/main/java/net/sf/jabref/logic/util/DOI.java index 753f88e53eb6..55cbfc614f1f 100644 --- a/src/main/java/net/sf/jabref/logic/util/DOI.java +++ b/src/main/java/net/sf/jabref/logic/util/DOI.java @@ -7,6 +7,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.sf.jabref.importer.fetcher.CrossRef; +import net.sf.jabref.model.entry.BibEntry; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -120,6 +123,16 @@ public static Optional findInText(String text) { return result; } + /** + * Tries to retrieve a DOI for an existing BibEntry. + * + * @param entry the BibteX entry + * @return an Optional containing the DOI or an empty Optional + */ + public static Optional fromBibEntry(BibEntry entry) { + return CrossRef.findDOI(entry); + } + /** * Return the plain DOI * diff --git a/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java b/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java index c826d0203f22..e1e6e7c390d7 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/CrossRefTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.importer.fetcher; import java.util.Locale; +import java.util.Optional; import net.sf.jabref.model.entry.BibEntry; @@ -34,13 +35,29 @@ public void findTitleOnly() { } @Test - public void findIncompleteTitle() { + public void notFindIncompleteTitle() { BibEntry entry = new BibEntry(); entry.setField("title", "Towards Application Portability"); entry.setField("author", "Stefan Kolb and Guido Wirtz"); + assertEquals(Optional.empty(), CrossRef.findDOI(entry)); + } + + @Test + public void acceptTitleUnderThreshold() { + BibEntry entry = new BibEntry(); + entry.setField("title", "Towards Application Portability in Platform as a Service----"); + entry.setField("author", "Stefan Kolb and Guido Wirtz"); assertEquals("10.1109/sose.2014.26", CrossRef.findDOI(entry).get().getDOI().toLowerCase(Locale.ENGLISH)); } + @Test + public void notAcceptTitleOverThreshold() { + BibEntry entry = new BibEntry(); + entry.setField("title", "Towards Application Portability in Platform as a Service-----"); + entry.setField("author", "Stefan Kolb and Guido Wirtz"); + assertEquals(Optional.empty(), CrossRef.findDOI(entry)); + } + @Test public void findWrongAuthor() { BibEntry entry = new BibEntry(); From 6f2feebec202b02149880a9f702c6a15d67bbfb5 Mon Sep 17 00:00:00 2001 From: tschechlovdev Date: Wed, 25 May 2016 16:42:59 +0200 Subject: [PATCH 103/268] add fields for nbibImporter and add testfile (#1397) * add nbib fields to medlineplain and add test * add nbib fields to medlineplain and add test * improve readability --- CHANGELOG.md | 1 + .../fileformat/MedlinePlainImporter.java | 394 ++++++++++++------ .../fileformat/MedlinePlainImporterTest.java | 7 + .../MedlinePlainImporterTestCompleteEntry.bib | 38 +- .../MedlinePlainImporterTestDOI.bib | 2 +- .../importer/fileformat/NbibImporterTest.bib | 47 +++ .../importer/fileformat/NbibImporterTest.nbib | 71 ++++ 7 files changed, 420 insertions(+), 140 deletions(-) create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.nbib diff --git a/CHANGELOG.md b/CHANGELOG.md index 311d1100178f..7488e31c1f1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Integrity check table can be sorted by clicking on column headings - Added \SOFTWARE\Jabref 'Path' registry entry for installation path inside the installer - Added an additional icon to distinguish DOI and URL links ([feature request #696](https://github.com/JabRef/jabref/issues/696)) +- Added nbib fields to Medlineplain importer - Implemented [#1342](https://github.com/JabRef/jabref/issues/1342): show description of case converters as tooltip ### Fixed diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index 00215f82b9d2..5884b79bbfd7 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; @@ -43,6 +44,9 @@ public class MedlinePlainImporter extends ImportFormat { private static final Pattern PMID_PATTERN = Pattern.compile("PMID.*-.*"); private static final Pattern PMC_PATTERN = Pattern.compile("PMC.*-.*"); private static final Pattern PMCR_PATTERN = Pattern.compile("PMCR.*-.*"); + private static final Pattern CREATE_DATE_PATTERN = Pattern.compile("\\d{4}/[0123]?\\d/\\s?[012]\\d:[0-5]\\d"); + private static final Pattern COMPLETE_DATE_PATTERN = Pattern.compile("\\d{8}"); + @Override public String getFormatName() { @@ -66,8 +70,8 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { // (i.e., PubMed Unique Identifier, PubMed Central Identifier, PubMed Central Release) String str; while ((str = reader.readLine()) != null) { - if (PMID_PATTERN.matcher(str).find() || PMC_PATTERN.matcher(str).find() || PMCR_PATTERN.matcher(str) - .find()) { + if (PMID_PATTERN.matcher(str).find() || PMC_PATTERN.matcher(str).find() + || PMCR_PATTERN.matcher(str).find()) { return true; } } @@ -96,26 +100,25 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { String author = ""; String editor = ""; String comment = ""; - Map hm = new HashMap<>(); + Map fields = new HashMap<>(); - String[] fields = entry1.split("\n"); + String[] lines = entry1.split("\n"); - for (int j = 0; j < fields.length; j++) { + for (int j = 0; j < lines.length; j++) { - StringBuilder current = new StringBuilder(fields[j]); + StringBuilder current = new StringBuilder(lines[j]); boolean done = false; - while (!done && (j < (fields.length - 1))) { - if (fields[j + 1].length() <= 4) { + while (!done && (j < (lines.length - 1))) { + if (lines[j + 1].length() <= 4) { j++; continue; } - if (fields[j + 1].charAt(4) != '-') { - if ((current.length() > 0) - && !Character.isWhitespace(current.charAt(current.length() - 1))) { + if (lines[j + 1].charAt(4) != '-') { + if ((current.length() > 0) && !Character.isWhitespace(current.charAt(current.length() - 1))) { current.append(' '); } - current.append(fields[j + 1].trim()); + current.append(lines[j + 1].trim()); j++; } else { done = true; @@ -123,148 +126,105 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } String entry = current.toString(); - String lab = entry.substring(0, entry.indexOf('-')).trim(); - String val = entry.substring(entry.indexOf('-') + 1).trim(); - if ("PT".equals(lab)) { - val = val.toLowerCase(); - if ("book".equals(val)) { - type = "book"; - } else if ("journal article".equals(val) - || "classical article".equals(val) - || "corrected and republished article".equals(val) - || "historical article".equals(val) - || "introductory journal article".equals(val) - || "newspaper article".equals(val)) { - type = "article"; - } else if ("clinical conference".equals(val) - || "consensus development conference".equals(val) - || "consensus development conference, nih".equals(val)) { - type = "conference"; - } else if ("technical report".equals(val)) { - type = "techreport"; - } else if ("editorial".equals(val)) { - type = "inproceedings";//"incollection";"inbook"; - } else if ("overall".equals(val)) { - type = "proceedings"; - } else if ("".equals(type)) { - type = "other"; - } + String label = entry.substring(0, entry.indexOf('-')).trim(); + String value = entry.substring(entry.indexOf('-') + 1).trim(); - } else if ("TI".equals(lab)) { - String oldVal = hm.get("title"); - if (oldVal == null) { - hm.put("title", val); - } else { - if (oldVal.endsWith(":") || oldVal.endsWith(".") || oldVal.endsWith("?")) { - hm.put("title", oldVal + " " + val); - } else { - hm.put("title", oldVal + ": " + val); - } - } + if ("PT".equals(label)) { + type = addSourceType(value, type); } - // = - // val; - else if ("BTI".equals(lab) || "CTI".equals(lab)) { - hm.put("booktitle", val); - } else if ("FAU".equals(lab)) { + addDates(fields, label, value); + addAbstract(fields, label, value); + addTitles(fields, label, value, type); + addIDs(fields, label, value); + addStandardNumber(fields, label, value); + + if ("FAU".equals(label)) { if ("".equals(author)) { - author = val; + author = value; } else { - author += " and " + val; + author += " and " + value; } - } else if ("FED".equals(lab)) { + } else if ("FED".equals(label)) { if ("".equals(editor)) { - editor = val; + editor = value; } else { - editor += " and " + val; + editor += " and " + value; } - } else if ("JT".equals(lab)) { - if ("inproceedings".equals(type)) { - hm.put("booktitle", val); - } else { - hm.put("journal", val); + } + + //store the fields in a map + Map hashMap = new HashMap<>(); + hashMap.put("PG", "pages"); + hashMap.put("PL", "address"); + hashMap.put("PHST", "history"); + hashMap.put("PST", "publication-status"); + hashMap.put("VI", "volume"); + hashMap.put("LA", "language"); + hashMap.put("LA", "language"); + hashMap.put("PUBM", "model"); + hashMap.put("RN", "registry-number"); + hashMap.put("NM", "substance-name"); + hashMap.put("OCI", "copyright-owner"); + hashMap.put("CN", "corporate"); + hashMap.put("IP", "issue"); + hashMap.put("EN", "edition"); + hashMap.put("GS", "gene-symbol"); + hashMap.put("GN", "note"); + hashMap.put("GR", "grantno"); + hashMap.put("SO", "source"); + hashMap.put("NR", "number-of-references"); + hashMap.put("SFM", "space-flight-mission"); + hashMap.put("STAT", "status"); + hashMap.put("SB", "subset"); + hashMap.put("OTO", "termowner"); + hashMap.put("OWN", "owner"); + + //add the fields to hm + for (Map.Entry mapEntry : hashMap.entrySet()) { + String medlineKey = mapEntry.getKey(); + String bibtexKey = mapEntry.getValue(); + if (medlineKey.equals(label)) { + fields.put(bibtexKey, value); } - } else if ("PG".equals(lab)) { - hm.put("pages", val); - } else if ("PL".equals(lab)) { - hm.put("address", val); - } else if ("IS".equals(lab)) { - hm.put("issn", val); - } else if ("VI".equals(lab)) { - hm.put("volume", val); - } else if ("AB".equals(lab)) { - String oldAb = hm.get("abstract"); - if (oldAb == null) { - hm.put("abstract", val); + } + + if ("IRAD".equals(label) || "IR".equals(label) || "FIR".equals(label)) { + String oldInvestigator = fields.get("investigator"); + if (oldInvestigator == null) { + fields.put("investigator", value); } else { - hm.put("abstract", oldAb + Globals.NEWLINE + val); - } - } else if ("DP".equals(lab)) { - String[] parts = val.split(" "); - hm.put("year", parts[0]); - if ((parts.length > 1) && !parts[1].isEmpty()) { - hm.put("month", parts[1]); + fields.put("investigator", oldInvestigator + ", " + value); } - } else if ("MH".equals(lab) || "OT".equals(lab)) { - if (!hm.containsKey("keywords")) { - hm.put("keywords", val); + } else if ("MH".equals(label) || "OT".equals(label)) { + if (!fields.containsKey("keywords")) { + fields.put("keywords", value); } else { - String kw = hm.get("keywords"); - hm.put("keywords", kw + ", " + val); + String kw = fields.get("keywords"); + fields.put("keywords", kw + ", " + value); } - } else if ("CON".equals(lab) || "CIN".equals(lab) || "EIN".equals(lab) - || "EFR".equals(lab) || "CRI".equals(lab) || "CRF".equals(lab) - || "PRIN".equals(lab) || "PROF".equals(lab) || "RPI".equals(lab) - || "RPF".equals(lab) || "RIN".equals(lab) || "ROF".equals(lab) - || "UIN".equals(lab) || "UOF".equals(lab) || "SPIN".equals(lab) - || "ORI".equals(lab)) { + } else if ("CON".equals(label) || "CIN".equals(label) || "EIN".equals(label) || "EFR".equals(label) + || "CRI".equals(label) || "CRF".equals(label) || "PRIN".equals(label) || "PROF".equals(label) + || "RPI".equals(label) || "RPF".equals(label) || "RIN".equals(label) || "ROF".equals(label) + || "UIN".equals(label) || "UOF".equals(label) || "SPIN".equals(label) || "ORI".equals(label)) { if (!comment.isEmpty()) { comment = comment + "\n"; } - comment = comment + val; - } - // // Added ID import 2005.12.01, Morten Alver: - // else if (lab.equals("ID")) - // hm.put("refid", val); - // // Added doi import (sciencedirect.com) 2011.01.10, Alexander Hug - else if ("AID".equals(lab)) { - String doi = val; - if (doi.startsWith("doi:")) { - doi = doi.replaceAll("(?i)doi:", "").trim(); - hm.put("doi", doi); - } + comment = comment + value; } } - // fix authors - if (!author.isEmpty()) { - author = AuthorList.fixAuthorLastNameFirst(author); - hm.put("author", author); - } - if (!editor.isEmpty()) { - editor = AuthorList.fixAuthorLastNameFirst(editor); - hm.put("editor", editor); - } + fixAuthors(fields, author, "author"); + fixAuthors(fields, editor, "editor"); if (!comment.isEmpty()) { - hm.put("comment", comment); + fields.put("comment", comment); } BibEntry b = new BibEntry(DEFAULT_BIBTEXENTRY_ID, type); // id assumes an existing database so don't // Remove empty fields: - List toRemove = new ArrayList<>(); - for (Map.Entry key : hm.entrySet()) { - String content = key.getValue(); - // content can never be null so only check if content is empty - if (content.trim().isEmpty()) { - toRemove.add(key.getKey()); - } - } - for (Object aToRemove : toRemove) { - hm.remove(aToRemove); - } + fields.entrySet().stream().filter(n -> n.getValue().trim().isEmpty()).forEach(fields::remove); // create one here - b.setField(hm); + b.setField(fields); bibitems.add(b); } @@ -272,4 +232,182 @@ else if ("AID".equals(lab)) { return new ParserResult(bibitems); } + + private String addSourceType(String value, String type) { + String val = value.toLowerCase(Locale.ENGLISH); + String theType = type; + switch (val) { + case "book": + theType = "book"; + break; + case "journal article": + case "classical article": + case "corrected and republished article": + case "historical article": + case "introductory journal article": + case "newspaper article": + theType = "article"; + break; + case "clinical conference": + case "consensus development conference": + case "consensus development conference, nih": + theType = "conference"; + break; + case "technical report": + theType = "techreport"; + break; + case "editorial": + theType = "inproceedings"; + break; + case "overall": + theType = "proceedings"; + break; + } + if ("".equals(theType)) { + theType = "other"; + } + return theType; + } + + private void addStandardNumber(Map hm, String lab, String value) { + if ("IS".equals(lab)) { + String key = "issn"; + //it is possible to have two issn, one for electronic and for print + //if there are two then it comes at the end in brackets (electronic) or (print) + //so search for the brackets + if (value.indexOf('(') > 0) { + int keyStart = value.indexOf('('); + int keyEnd = value.indexOf(')'); + key = value.substring(keyStart + 1, keyEnd) + "-" + key; + String numberValue = value.substring(0, keyStart - 1); + hm.put(key, numberValue); + } else { + hm.put(key, value); + } + } else if ("ISBN".equals(lab)) { + hm.put("isbn", value); + } + } + + private void fixAuthors(Map hm, String author, String field) { + if (!author.isEmpty()) { + String fixedAuthor = AuthorList.fixAuthorLastNameFirst(author); + hm.put(field, fixedAuthor); + } + } + + private void addIDs(Map hm, String lab, String value) { + if ("AID".equals(lab)) { + String key = "article-id"; + String idValue = value; + if (value.startsWith("doi:")) { + idValue = idValue.replaceAll("(?i)doi:", "").trim(); + key = "doi"; + } else if (value.indexOf('[') > 0) { + int startOfIdentifier = value.indexOf('['); + int endOfIdentifier = value.indexOf(']'); + key = "article-" + value.substring(startOfIdentifier + 1, endOfIdentifier); + idValue = value.substring(0, startOfIdentifier - 1); + } + hm.put(key, idValue); + + } else if ("LID".equals(lab)) { + hm.put("location-id", value); + } else if ("MID".equals(lab)) { + hm.put("manuscript-id", value); + } else if ("JID".equals(lab)) { + hm.put("nlm-unique-id", value); + } else if ("OID".equals(lab)) { + hm.put("other-id", value); + } else if ("SI".equals(lab)) { + hm.put("second-id", value); + } + } + + private void addTitles(Map hm, String lab, String val, String type) { + if ("TI".equals(lab)) { + String oldVal = hm.get("title"); + if (oldVal == null) { + hm.put("title", val); + } else { + if (oldVal.endsWith(":") || oldVal.endsWith(".") || oldVal.endsWith("?")) { + hm.put("title", oldVal + " " + val); + } else { + hm.put("title", oldVal + ": " + val); + } + } + } else if ("BTI".equals(lab) || "CTI".equals(lab)) { + hm.put("booktitle", val); + } else if ("JT".equals(lab)) { + if ("inproceedings".equals(type)) { + hm.put("booktitle", val); + } else { + hm.put("journal", val); + } + } else if ("CTI".equals(lab)) { + hm.put("collection-title", val); + } else if ("TA".equals(lab)) { + hm.put("title-abbreviation", val); + } else if ("TT".equals(lab)) { + hm.put("transliterated-title", val); + } else if ("VTI".equals(lab)) { + hm.put("volume-title", val); + } + } + + private void addAbstract(Map hm, String lab, String value) { + String abstractValue = ""; + if ("AB".equals(lab)) { + //adds copyright information that comes at the end of an abstract + if (value.contains("Copyright")) { + int copyrightIndex = value.lastIndexOf("Copyright"); + //remove the copyright from the field since the name of the field is copyright + String copyrightInfo = value.substring(copyrightIndex, value.length()).replaceAll("Copyright ", ""); + hm.put("copyright", copyrightInfo); + abstractValue = value.substring(0, copyrightIndex); + } else { + abstractValue = value; + } + String oldAb = hm.get("abstract"); + if (oldAb == null) { + hm.put("abstract", abstractValue); + } else { + hm.put("abstract", oldAb + Globals.NEWLINE + abstractValue); + } + } else if ("OAB".equals(lab) || "OABL".equals(lab)) { + hm.put("other-abstract", value); + } + } + + private void addDates(Map hm, String lab, String val) { + if ("CRDT".equals(lab) && isCreateDateFormat(val)) { + hm.put("create-date", val); + } else if ("DEP".equals(lab) && isDateFormat(val)) { + hm.put("electronic-publication", val); + } else if ("DA".equals(lab) && isDateFormat(val)) { + hm.put("date-created", val); + } else if ("DCOM".equals(lab) && isDateFormat(val)) { + hm.put("completed", val); + } else if ("LR".equals(lab) && isDateFormat(val)) { + hm.put("revised", val); + } else if ("DP".equals(lab)) { + String[] parts = val.split(" "); + hm.put("year", parts[0]); + if ((parts.length > 1) && !parts[1].isEmpty()) { + hm.put("month", parts[1]); + } + } else if ("EDAT".equals(lab) && isCreateDateFormat(val)) { + hm.put("publication", val); + } else if ("MHDA".equals(lab) && isCreateDateFormat(val)) { + hm.put("mesh-date", val); + } + } + + private boolean isCreateDateFormat(String value) { + return CREATE_DATE_PATTERN.matcher(value).matches(); + } + + private boolean isDateFormat(String value) { + return COMPLETE_DATE_PATTERN.matcher(value).matches(); + } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index dc795c78ffaf..a9ebc8029e06 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -171,6 +171,13 @@ public void testKeyWords() throws IOException { } } + @Test + public void testWithNbibFile() throws IOException, URISyntaxException { + Path file = Paths.get(MedlinePlainImporter.class.getResource("NbibImporterTest.nbib").toURI()); + List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + BibEntryAssert.assertEquals(MedlinePlainImporter.class, "NbibImporterTest.bib", entries); + } + @Test public void testAllArticleTypes() throws IOException { try (BufferedReader reader = readerForString("PMID-22664795" + "\n" + diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestCompleteEntry.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestCompleteEntry.bib index 7721e3c763e4..02ebcde01525 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestCompleteEntry.bib +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestCompleteEntry.bib @@ -1,12 +1,28 @@ -@Article{, - Title = {From danger and motherhood to health and beauty: health advice for the factory girl in early twentieth-century Britain.}, - Author = {Long, Vicky and Marland, Hilary}, - Journal = {20 century British history}, - Year = {2009}, - Pages = {454-81}, - Volume = {20}, - Abstract = {Lorem ipsum abstract}, - Address = {England}, - ISSN = {0955-2359 (Linking)}, - Keywords = {Attitude to Health, Employment/psychology, Female, Gender Identity, Great Britain, History, 20th Century, Humans, Occupational Health/*history, Reproductive Medicine/*history, Women, Working/*history/psychology} +@article{, + abstract = {Lorem ipsum abstract}, + address = {England}, + author = {Long, Vicky and Marland, Hilary}, + completed = {20100526}, + date-created = {20100520}, + grantno = {076053/Wellcome Trust/United Kingdom}, + issue = {4}, + journal = {20 century British history}, + keywords = {Attitude to Health, Employment/psychology, Female, Gender Identity, Great Britain, History, 20th Century, Humans, Occupational Health/*history, Reproductive Medicine/*history, Women, Working/*history/psychology}, + language = {eng}, + linking-issn = {0955-2359}, + manuscript-id = {EMS54115}, + nlm-unique-id = {9015384}, + other-id = {NLM: PMC4513071}, + owner = {NLM}, + pages = {454-81}, + print-issn = {0955-2359}, + publication-status = {ppublish}, + revised = {20150731}, + source = {20 Century Br Hist. 2009;20(4):454-81.}, + status = {MEDLINE}, + subset = {QIS}, + title = {From danger and motherhood to health and beauty: health advice for the factory girl in early twentieth-century Britain.}, + title-abbreviation = {20 Century Br Hist}, + volume = {20}, + year = {2009} } diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestDOI.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestDOI.bib index 83728eba8da1..c4e061c9f3db 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestDOI.bib +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlinePlainImporterTestDOI.bib @@ -1,3 +1,3 @@ @TechReport{, - DOI = {10.1016/j.cpr.2005.02.002} + doi = {10.1016/j.cpr.2005.02.002} } diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.bib b/src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.bib new file mode 100644 index 000000000000..cad8dd6e27af --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.bib @@ -0,0 +1,47 @@ +@article{, + abstract = {some things will be described }, + address = {India}, + article-doi = {10.4103/2277-9175.180636}, + article-pii = {ABR-5-67}, + author = {Shruthi, Basavaradhya Sahukar and Vinodhkumar, Palani and Selvamani}, + booktitle = {name of collection}, + completed = {20160512}, + copyright = {2015 Tschechlov Press.}, + copyright-owner = {Copyright belongs to someone}, + corporate = {corporater}, + date-created = {20160512}, + edition = {2}, + electronic-issn = {2277-9175}, + electronic-publication = {20160419}, + gene-symbol = {a gene symbol}, + history = {2016/04/19 [epublish]}, + investigator = {Some investigator, one more investigator, last investigator}, + isbn = {ISBN 978-3-86680-192-9}, + journal = {Advanced biomedical research}, + keywords = {Biomarkers, electrophoresis, neoplasia, spectrometry, translation}, + language = {eng}, + linking-issn = {2277-9175}, + location-id = {10.4103/2277-9175.180636 [doi]}, + model = {a model}, + nlm-unique-id = {101586897}, + note = {some notes about the article}, + number-of-references = {25}, + other-abstract = {other abstract infos}, + owner = {NLM}, + pages = {67}, + publication-status = {epublish}, + registry-number = {123456789}, + second-id = {12563}, + source = {Adv Biomed Res. 2016 Apr 19;5:67. doi: 10.4103/2277-9175.180636. eCollection 2016.}, + space-flight-mission = {a space flight mission}, + status = {PubMed-not-MEDLINE}, + substance-name = {substance name}, + termowner = {NOTNLM}, + title = {Proteomics: A new perspective for cancer.}, + title-abbreviation = {Adv Biomed Res}, + transliterated-title = {title that is transliterated}, + volume = {5}, + volume-title = {title of the volume}, + year = {2016} + } + \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.nbib b/src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.nbib new file mode 100644 index 000000000000..65a77745e257 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/NbibImporterTest.nbib @@ -0,0 +1,71 @@ +PMID- 27169098 +OWN - NLM +STAT- PubMed-not-MEDLINE +DA - 20160512 +DCOM- 20160512 +IS - 2277-9175 (Electronic) +IS - 2277-9175 (Linking) +VI - 5 +DP - 2016 +TI - Proteomics: A new perspective for cancer. +PG - 67 +LID - 10.4103/2277-9175.180636 [doi] +AB - some things will be described Copyright 2015 Tschechlov Press. +FAU - Shruthi, Basavaradhya Sahukar +AU - Shruthi BS +AD - Department of Oral and Maxillofacial Pathology and Microbiology, Vishnu Dental + College, Vishnupur, Bhimavarm, Andhra Pradesh, India. +FAU - Vinodhkumar, Palani +AU - Vinodhkumar P +AD - Department of Pedodontics, Sri Balaji Dental College and Hospital, Chennai, Tamil + Nadu, India. +FAU - Selvamani +AU - Selvamani +AD - Department of Oral and Maxillofacial Pathology and Microbiology, College of + Dental Sciences, Davangere, Karnataka, India. +IRAD- Some investigator +IR - one more investigator +FIR - last investigator +LA - eng +GN - some notes about the article +GS - a gene symbol +EN - 2 +CN - corporater +OCI - Copyright belongs to someone +NM - substance name +RN - 123456789 +PUBM- a model +ISBN- ISBN 978-3-86680-192-9 +SI - 12563 +CTI - name of collection +TT - title that is transliterated +VTI - title of the volume +OAB - abstract informations +OABL- other abstract infos +PT - Journal Article +PT - Review +DEP - 20160419 +PL - India +TA - Adv Biomed Res +JT - Advanced biomedical research +JID - 101586897 +OTO - NOTNLM +OT - Biomarkers +OT - electrophoresis +OT - neoplasia +OT - spectrometry +OT - translation +SFM - a space flight mission +NR - 25 +EDAT- 2016/05/12 06:00 +MHDA- 2016/05/12 06:00 +CRDT- 2016/05/12 06:00 +PHST- 2016 [ecollection] +PHST- 2013/02/18 [received] +PHST- 2013/04/09 [accepted] +PHST- 2016/04/19 [epublish] +AID - 10.4103/2277-9175.180636 [doi] +AID - ABR-5-67 [pii] +PST - epublish +SO - Adv Biomed Res. 2016 Apr 19;5:67. doi: 10.4103/2277-9175.180636. eCollection + 2016. From d6c46ad3249ebdc25978255c4c1333af7a93f560 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 26 May 2016 18:09:00 +0200 Subject: [PATCH 104/268] Updated German translation --- CHANGELOG.md | 1 + src/main/resources/l10n/JabRef_de.properties | 128 +++++++++---------- 2 files changed, 65 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7488e31c1f1f..05196f8e9c94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Added an additional icon to distinguish DOI and URL links ([feature request #696](https://github.com/JabRef/jabref/issues/696)) - Added nbib fields to Medlineplain importer - Implemented [#1342](https://github.com/JabRef/jabref/issues/1342): show description of case converters as tooltip +- Updated German translation ### Fixed - Fixed [#473](https://github.com/JabRef/jabref/issues/473): Values in an entry containing symbols like ' are now properly escaped for exporting to the database diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index b4d9f8187004..e50c261d2133 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2332,74 +2332,74 @@ Female_names=weibliche_Namen Male_name=männlicher_Name Male_names=männliche_Namen Mixed_names=gemischte_Namen -Neuter_name=neutrischer_Name -Neuter_names=neutrische_Namen +Neuter_name=neutraler_Name +Neuter_names=neutrale_Namen Lookup_DOI=Suche_DOI -No_DOI_found=Kein_DOI_gefunden - -Audio_CD= -British_patent= -British_patent_request= -Candidate_thesis= -Collaborator= -Column= -Compiler= -Continuator= -Data_CD= -Editor= -European_patent= -European_patent_request= -Founder= -French_patent= -French_patent_request= -German_patent= -German_patent_request= -Line= -Master's_thesis= -Page= -Paragraph= -Patent= -Patent_request= -PhD_thesis= -Redactor= -Research_report= -Reviser= -Section= -Software= -Technical_report= -U.S._patent= -U.S._patent_request= -Verse= - -change_entries_of_group= -odd_number_of_unescaped_'\#'= -Plain_text= -Show_diff= -character= -word= - -Show_symmetric_diff= - -HTML_encoded_character_found= - -booktitle_ends_with_'conference_on'= -All_external_files= - -OpenOffice/LibreOffice_integration= - -incorrect_control_digit= -incorrect_format= - -Expected_"%0"_to_contain_whitespace= -Syntax_error_in_regular-expression_pattern= +No_DOI_found=Keine_DOI_gefunden + +Audio_CD=Audio_CD +British_patent=Britisches_Patent +British_patent_request=Britischer_Patentantrag +Candidate_thesis=Beliebige_Abschlussarbeit +Collaborator=Mitarbeiter +Column=Spalte +Compiler=Zusammensteller +Continuator=Fortsetzer +Data_CD=Daten_CD +Editor=Herausgeber +European_patent=Europäisches_Patent +European_patent_request=Europäischer_Patentantrag +Founder=Gründer +French_patent=Französisches_Patent +French_patent_request=Französischer_Patentantrag +German_patent=Deutsches_Patent +German_patent_request=Deutscher_Patentantrag +Line=Zeilennummer +Master's_thesis=Master/Magisterarbeit +Page=Seite +Paragraph=Abschnitt +Patent=Patent +Patent_request=Patentantrag +PhD_thesis=Dissertation +Redactor=Redaktor +Research_report=Forschungsbericht +Reviser=Sekundärer_Herausgeber +Section=Paragraph +Software=Programm +Technical_report=Technischer_Bericht +U.S._patent=Patent_der_Vereinigen_Staaten +U.S._patent_request=Patentantrag_der_Vereinigten_Staaten +Verse=Vers + +change_entries_of_group=Ändere_Einträge_der_Gruppe +odd_number_of_unescaped_'\#'=Ungerade_Anzahl_an_'\#'_Maskierungszeichen +Plain_text=Klartext +Show_diff=Zeige_Änderungen +character=Zeichen +word=Wort + +Show_symmetric_diff=Zeige_Änderungen_symmetisch + +HTML_encoded_character_found=HTML_kodiertes_Zeichen_gefunden + +booktitle_ends_with_'conference_on'=Buchtitel_endet_mit_'Konferenzbericht' +All_external_files=Alle_externen_Dateien + +OpenOffice/LibreOffice_integration=OpenOffice/LibreOffice-Integration + +incorrect_control_digit=Falsche_Prüfziffer +incorrect_format=Falsches_Format + +Expected_"%0"_to_contain_whitespace=Erwartete_Leerzeichen_in_"%0" +Syntax_error_in_regular-expression_pattern=Syntaxfehler_in_Regulärem_Ausdruck Copy_version_to_clipboard=Kopiere_Version_in_die_Zwischenablage Copied_version_to_clipboard=Version_in_die_Zwischenablage_kopiert -BibTeX_key= -Message= +BibTeX_key=BibTeX-Key +Message=Nachricht -Get_fulltext= +Get_fulltext=Hole_Volltext -Download_from_URL= +Download_from_URL=Download_von_URL -Decryption_not_supported.= +Decryption_not_supported.=Entschlüsselung_wird_nicht_unterstützt. From 2cef8e19b4c66f90e72009244b312ad208982635 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Fri, 27 May 2016 09:07:56 +0200 Subject: [PATCH 105/268] Add missing german translation key --- src/main/resources/l10n/JabRef_de.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index e50c261d2133..bcfd090fadf7 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2323,7 +2323,7 @@ This_operation_requires_exactly_one_item_to_be_selected.=Für_diesen_Vorgang_mus Directory_not_found=Verzeichnis_nicht_gefunden -Move_linked_files_to_default_file_directory_%0= +Move_linked_files_to_default_file_directory_%0=Verknüpfte_Dateien_in_das_Standardverzeichnis_%0_verschieben wrong_entry_type_as_proceedings_has_page_numbers=falscher_Eintragstyp,_weil_'Konferenzbericht'_Feld_mit_Seitenzahlen_hat Importing_in_%0_format=Importiere_im_Format_%0 From 72b25c3f5ed8f0895cfe3edfc795a64521a50245 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Sat, 28 May 2016 15:17:30 +0200 Subject: [PATCH 106/268] Fix #1425 by using a timer facility --- .../net/sf/jabref/JabRefExecutorService.java | 9 ++++ .../java/net/sf/jabref/gui/BasePanel.java | 45 +++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefExecutorService.java b/src/main/java/net/sf/jabref/JabRefExecutorService.java index 4ef232ffc5b5..f1e283f2f99e 100644 --- a/src/main/java/net/sf/jabref/JabRefExecutorService.java +++ b/src/main/java/net/sf/jabref/JabRefExecutorService.java @@ -15,6 +15,8 @@ */ package net.sf.jabref; +import java.util.Timer; +import java.util.TimerTask; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -43,6 +45,8 @@ public class JabRefExecutorService implements Executor { }); private final ConcurrentLinkedQueue startedThreads = new ConcurrentLinkedQueue<>(); + private final Timer timer = new Timer("timer"); + private JabRefExecutorService() {} @Override @@ -136,12 +140,17 @@ private void waitForThreadToFinish(Thread thread) { } } + public void submit(TimerTask timerTask, long millisecondsDelay) { + timer.schedule(timerTask, millisecondsDelay); + } + public void shutdownEverything() { this.executorService.shutdown(); for(Thread thread : startedThreads) { thread.interrupt(); } startedThreads.clear(); + timer.cancel(); } } diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index be34572625fa..8362259f3bad 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -38,6 +38,8 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Timer; +import java.util.TimerTask; import javax.swing.AbstractAction; import javax.swing.BorderFactory; @@ -1245,6 +1247,27 @@ public SearchBar getSearchBar() { private class GroupTreeListener { + private final Runnable task = new Runnable() { + @Override + public void run() { + // Update group display (for example to reflect that the number of contained entries has changed) + frame.getGroupSelector().revalidateGroups(); + } + + }; + + /** + * Only access when you have the lock of the task instance + * + * Guarded by "task" + */ + private TimerTask timerTask = new TimerTask() { + @Override + public void run() { + task.run(); + } + }; + @Subscribe public void listen(EntryAddedEvent addedEntryEvent) { // Automatically add new entry to the selected group (or set of groups) @@ -1260,14 +1283,28 @@ public void listen(EntryAddedEvent addedEntryEvent) { SwingUtilities.invokeLater(() -> BasePanel.this.getGroupSelector().valueChanged(null)); } - // Update group display (for example to reflect that the number of contained entries has changed) - frame.getGroupSelector().revalidateGroups(); + scheduleUpdate(); + } + + private void scheduleUpdate() { + // This is a quickfix/dirty hack. + // a better solution would be using RxJava or something reactive instead + // nevertheless it works correctly + synchronized (task) { + timerTask.cancel(); + timerTask = new TimerTask() { + @Override + public void run() { + task.run(); + } + }; + JabRefExecutorService.INSTANCE.submit(timerTask, 200); + } } @Subscribe public void listen(EntryChangedEvent entryChangedEvent) { - // Update group display in order to take changes into account - frame.getGroupSelector().revalidateGroups(); + scheduleUpdate(); } } From 886136dc6b252dd62d36fa1fe895ee7746e56dbc Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Sat, 28 May 2016 16:20:56 +0200 Subject: [PATCH 107/268] Remove unused imports --- src/main/java/net/sf/jabref/gui/BasePanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 8362259f3bad..a9b158f1cf9c 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -38,7 +38,6 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Timer; import java.util.TimerTask; import javax.swing.AbstractAction; From edbc9be052c8d37f4d78b5067fe020c7e3377c5b Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Mon, 30 May 2016 14:49:55 +0200 Subject: [PATCH 108/268] Fix #1455 NPE when retrieving BibteX data from DOI --- .../java/net/sf/jabref/gui/ClipBoardManager.java | 2 +- .../gui/mergeentries/MergeEntryDOIDialog.java | 2 +- .../importer/fetcher/DOItoBibTeXFetcher.java | 15 ++++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/ClipBoardManager.java b/src/main/java/net/sf/jabref/gui/ClipBoardManager.java index 9071de0a384f..2095e8123de9 100644 --- a/src/main/java/net/sf/jabref/gui/ClipBoardManager.java +++ b/src/main/java/net/sf/jabref/gui/ClipBoardManager.java @@ -105,7 +105,7 @@ public List extractBibEntriesFromClipboard() { // fetch from doi if (DOI.build(data).isPresent()) { LOGGER.info("Found DOI in clipboard"); - BibEntry entry = new DOItoBibTeXFetcher().getEntryFromDOI(new DOI(data).getDOI(), null); + BibEntry entry = new DOItoBibTeXFetcher().getEntryFromDOI(new DOI(data).getDOI()); if (entry != null) { result.add(entry); } diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java index 8b7d19c96c08..1f98aab4ecee 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java @@ -72,7 +72,7 @@ public MergeEntryDOIDialog(BasePanel panel) { this.originalEntry = panel.getSelectedEntries().get(0); panel.output(Localization.lang("Fetching info based on DOI")); - this.doiEntry = doiFetcher.getEntryFromDOI(this.originalEntry.getField("doi"), null); + this.doiEntry = doiFetcher.getEntryFromDOI(this.originalEntry.getField("doi")); if (this.doiEntry == null) { panel.output(""); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index d83c1c771945..be06dacf3c67 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -22,7 +22,6 @@ import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.Objects; import java.util.Optional; import javax.swing.JPanel; @@ -86,14 +85,18 @@ public JPanel getOptionsPanel() { return null; } - public BibEntry getEntryFromDOI(String doiStr, ParserResult parserResult) { - Objects.requireNonNull(parserResult); + public BibEntry getEntryFromDOI(String doiStr) { + return getEntryFromDOI(doiStr, null); + } + public BibEntry getEntryFromDOI(String doiStr, ParserResult parserResult) { DOI doi; try { doi = new DOI(doiStr); } catch (IllegalArgumentException e) { - parserResult.addWarning(Localization.lang("Invalid DOI: '%0'.", doiStr)); + if (parserResult != null) { + parserResult.addWarning(Localization.lang("Invalid DOI: '%0'.", doiStr)); + } return null; } @@ -119,7 +122,9 @@ public BibEntry getEntryFromDOI(String doiStr, ParserResult parserResult) { dl.addParameters("Accept", "application/x-bibtex"); bibtexString = dl.downloadToString(StandardCharsets.UTF_8); } catch (FileNotFoundException e) { - parserResult.addWarning(Localization.lang("Unknown DOI: '%0'.", doi.getDOI())); + if (parserResult != null) { + parserResult.addWarning(Localization.lang("Unknown DOI: '%0'.", doi.getDOI())); + } LOGGER.debug("Unknown DOI", e); return null; } catch (IOException e) { From a14ad8e6b10bff8c129ffc7edd56ba0c33b1deda Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Mon, 30 May 2016 16:27:42 +0200 Subject: [PATCH 109/268] Fix RTF formatter bug (#1461) * Add test for bug #1457 * Fix #1457 Support multiple words inside LaTeX commands to RTF export * Changelog --- CHANGELOG.md | 3 +- .../jabref/logic/layout/format/RTFChars.java | 8 +- .../jabref/logic/util/strings/RtfCharMap.java | 10 +- .../logic/layout/format/RTFCharsTest.java | 121 +++++++++--------- 4 files changed, 69 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05196f8e9c94..5a74ad6665a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,8 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1412](https://github.com/JabRef/jabref/issues/1412): Save action *protect terms* protects terms within words unecessarily - Fixed [#1420](https://github.com/JabRef/jabref/issues/1420): Auto downloader should respect file pattern and propose correct filename - Fixed [#651](https://github.com/JabRef/jabref/issues/651): Improve parsing of author names containing braces -- Fixed [#1421](https://github.com/JabRef/jabref/issues/1421):Auto downloader should try to retrieve DOI if not present and fetch afterwards +- Fixed [#1421](https://github.com/JabRef/jabref/issues/1421): Auto downloader should try to retrieve DOI if not present and fetch afterwards +- Fixed [#1457](https://github.com/JabRef/jabref/issues/1457): Support multiple words inside LaTeX commands to RTF export ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/logic/layout/format/RTFChars.java b/src/main/java/net/sf/jabref/logic/layout/format/RTFChars.java index be207ca0fe8f..c7c5f5c87253 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/RTFChars.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/RTFChars.java @@ -39,16 +39,12 @@ * 5.) Replace --- by \emdash and -- by \endash. */ public class RTFChars implements LayoutFormatter { - - // Instantiate logger: private static final Log LOGGER = LogFactory.getLog(LayoutFormatter.class); private static final RtfCharMap RTF_CHARS = new RtfCharMap(); - @Override public String format(String field) { - StringBuilder sb = new StringBuilder(""); StringBuilder currentCommand = null; boolean escaped = false; @@ -133,7 +129,7 @@ else if (c == '\\') { // Then look for italics etc., // but first check if we are already at the end of the string. - if (i >= (field.length() - 1)) { + if (i >= field.length() - 1) { break testContent; } @@ -204,7 +200,7 @@ private StringInt getPart(String text, int i, boolean commandNestedInBraces) { count++; break; case ' ': - if (commandNestedInBraces) { + if (!commandNestedInBraces) { // in any case, a space terminates the loop break loop; } diff --git a/src/main/java/net/sf/jabref/logic/util/strings/RtfCharMap.java b/src/main/java/net/sf/jabref/logic/util/strings/RtfCharMap.java index bef6b75f8dcd..2e26c9b763a3 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/RtfCharMap.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/RtfCharMap.java @@ -2,11 +2,8 @@ import java.util.HashMap; - public class RtfCharMap extends HashMap { public RtfCharMap () { - - put("`a", "\\'e0"); put("`e", "\\'e8"); put("`i", "\\'ec"); @@ -59,7 +56,7 @@ public RtfCharMap () { put("\"A", "\\u196A"); // "Auml" put("AA", "\\u197A"); // "Aring" // RTFCHARS.put("AE", "{\\uc2\\u198AE}"); // "AElig" -put("AE", "{\\u198A}"); // "AElig" + put("AE", "{\\u198A}"); // "AElig" put("cC", "\\u199C"); // "Ccedil" put("`E", "\\u200E"); // "Egrave" put("'E", "\\u201E"); // "Eacute" @@ -97,7 +94,7 @@ public RtfCharMap () { put("\"a", "\\u228a"); // "auml" put("aa", "\\u229a"); // "aring" // RTFCHARS.put("ae", "{\\uc2\\u230ae}"); // "aelig" \\u230e6 -put("ae", "{\\u230a}"); // "aelig" \\u230e6 + put("ae", "{\\u230a}"); // "aelig" \\u230e6 put("cc", "\\u231c"); // "ccedil" put("`e", "\\u232e"); // "egrave" put("'e", "\\u233e"); // "eacute" @@ -122,7 +119,7 @@ public RtfCharMap () { put("'u", "\\u250u"); // "uacute" put("^u", "\\u251u"); // "ucirc" // RTFCHARS.put("\"u", "\\u252"); // "uuml" exists in standard -// codepage + // codepage put("'y", "\\u253y"); // "yacute" put("th", "{\\uc2\\u254th}"); // "thorn" put("\"y", "\\u255y"); // "yuml" @@ -256,5 +253,4 @@ public RtfCharMap () { put("vz", "\\u382z"); // "zcaron" // Symbol #383 (f) has no special Latex command } - } diff --git a/src/test/java/net/sf/jabref/logic/layout/format/RTFCharsTest.java b/src/test/java/net/sf/jabref/logic/layout/format/RTFCharsTest.java index fd2bfff1ee13..9fd8559ca83a 100644 --- a/src/test/java/net/sf/jabref/logic/layout/format/RTFCharsTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/format/RTFCharsTest.java @@ -2,95 +2,98 @@ import net.sf.jabref.logic.layout.LayoutFormatter; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; public class RTFCharsTest { + private LayoutFormatter formatter; - @Test - public void testBasicFormat() { + @Before + public void setUp() { + formatter = new RTFChars(); + } - LayoutFormatter layout = new RTFChars(); + @After + public void tearDown() { + formatter = null; + } - Assert.assertEquals("", layout.format("")); + @Test + public void testBasicFormat() { + Assert.assertEquals("", formatter.format("")); - Assert.assertEquals("hallo", layout.format("hallo")); + Assert.assertEquals("hallo", formatter.format("hallo")); // We should be able to replace the ? with e Assert.assertEquals("R\\u233?flexions sur le timing de la quantit\\u233?", - layout.format("Réflexions sur le timing de la quantité")); + formatter.format("Réflexions sur le timing de la quantité")); - Assert.assertEquals("h\\u225allo", layout.format("h\\'allo")); - Assert.assertEquals("h\\u225allo", layout.format("h\\'allo")); + Assert.assertEquals("h\\u225allo", formatter.format("h\\'allo")); + Assert.assertEquals("h\\u225allo", formatter.format("h\\'allo")); } @Test public void testLaTeXHighlighting() { + Assert.assertEquals("{\\i hallo}", formatter.format("\\emph{hallo}")); + Assert.assertEquals("{\\i hallo}", formatter.format("{\\emph hallo}")); + Assert.assertEquals("An article title with {\\i a book title} emphasized", formatter.format("An article title with \\emph{a book title} emphasized")); - LayoutFormatter layout = new RTFChars(); - - Assert.assertEquals("{\\i hallo}", layout.format("\\emph{hallo}")); - Assert.assertEquals("{\\i hallo}", layout.format("{\\emph hallo}")); - - Assert.assertEquals("{\\i hallo}", layout.format("\\textit{hallo}")); - Assert.assertEquals("{\\i hallo}", layout.format("{\\textit hallo}")); + Assert.assertEquals("{\\i hallo}", formatter.format("\\textit{hallo}")); + Assert.assertEquals("{\\i hallo}", formatter.format("{\\textit hallo}")); - Assert.assertEquals("{\\b hallo}", layout.format("\\textbf{hallo}")); - Assert.assertEquals("{\\b hallo}", layout.format("{\\textbf hallo}")); + Assert.assertEquals("{\\b hallo}", formatter.format("\\textbf{hallo}")); + Assert.assertEquals("{\\b hallo}", formatter.format("{\\textbf hallo}")); } @Test @Ignore public void testComplicated() { - LayoutFormatter layout = new RTFChars(); - Assert.assertEquals("R\\u233eflexions sur le timing de la quantit\\u233e \\u230ae should be \\u230ae", - layout.format("Réflexions sur le timing de la quantité \\ae should be æ")); + formatter.format("Réflexions sur le timing de la quantité \\ae should be æ")); - Assert.assertEquals("h\\u225all{\\uc2\\u339oe}", layout.format("h\\'all\\oe ")); + Assert.assertEquals("h\\u225all{\\uc2\\u339oe}", formatter.format("h\\'all\\oe ")); } @Test @Ignore public void testSpecialCharacters() { - - LayoutFormatter layout = new RTFChars(); - - Assert.assertEquals("\\u243o", layout.format("\\'{o}")); // ó - Assert.assertEquals("\\'f2", layout.format("\\`{o}")); // ò - Assert.assertEquals("\\'f4", layout.format("\\^{o}")); // ô - Assert.assertEquals("\\'f6", layout.format("\\\"{o}")); // ö - Assert.assertEquals("\\u245o", layout.format("\\~{o}")); // õ - Assert.assertEquals("\\u333o", layout.format("\\={o}")); - Assert.assertEquals("\\u334O", layout.format("\\u{o}")); - Assert.assertEquals("\\u231c", layout.format("\\c{c}")); // ç - Assert.assertEquals("{\\uc2\\u339oe}", layout.format("\\oe")); - Assert.assertEquals("{\\uc2\\u338OE}", layout.format("\\OE")); - Assert.assertEquals("{\\uc2\\u230ae}", layout.format("\\ae")); // æ - Assert.assertEquals("{\\uc2\\u198AE}", layout.format("\\AE")); // Æ - - Assert.assertEquals("", layout.format("\\.{o}")); // ??? - Assert.assertEquals("", layout.format("\\v{o}")); // ??? - Assert.assertEquals("", layout.format("\\H{a}")); // ã // ??? - Assert.assertEquals("", layout.format("\\t{oo}")); - Assert.assertEquals("", layout.format("\\d{o}")); // ??? - Assert.assertEquals("", layout.format("\\b{o}")); // ??? - Assert.assertEquals("", layout.format("\\aa")); // å - Assert.assertEquals("", layout.format("\\AA")); // Å - Assert.assertEquals("", layout.format("\\o")); // ø - Assert.assertEquals("", layout.format("\\O")); // Ø - Assert.assertEquals("", layout.format("\\l")); - Assert.assertEquals("", layout.format("\\L")); - Assert.assertEquals("{\\uc2\\u223ss}", layout.format("\\ss")); // ß - Assert.assertEquals("", layout.format("?`")); // ¿ - Assert.assertEquals("", layout.format("!`")); // ¡ - - Assert.assertEquals("", layout.format("\\dag")); - Assert.assertEquals("", layout.format("\\ddag")); - Assert.assertEquals("", layout.format("\\S")); // § - Assert.assertEquals("", layout.format("\\P")); // ¶ - Assert.assertEquals("", layout.format("\\copyright")); // © - Assert.assertEquals("", layout.format("\\pounds")); // £ + Assert.assertEquals("\\u243o", formatter.format("\\'{o}")); // ó + Assert.assertEquals("\\'f2", formatter.format("\\`{o}")); // ò + Assert.assertEquals("\\'f4", formatter.format("\\^{o}")); // ô + Assert.assertEquals("\\'f6", formatter.format("\\\"{o}")); // ö + Assert.assertEquals("\\u245o", formatter.format("\\~{o}")); // õ + Assert.assertEquals("\\u333o", formatter.format("\\={o}")); + Assert.assertEquals("\\u334O", formatter.format("\\u{o}")); + Assert.assertEquals("\\u231c", formatter.format("\\c{c}")); // ç + Assert.assertEquals("{\\uc2\\u339oe}", formatter.format("\\oe")); + Assert.assertEquals("{\\uc2\\u338OE}", formatter.format("\\OE")); + Assert.assertEquals("{\\uc2\\u230ae}", formatter.format("\\ae")); // æ + Assert.assertEquals("{\\uc2\\u198AE}", formatter.format("\\AE")); // Æ + + Assert.assertEquals("", formatter.format("\\.{o}")); // ??? + Assert.assertEquals("", formatter.format("\\v{o}")); // ??? + Assert.assertEquals("", formatter.format("\\H{a}")); // ã // ??? + Assert.assertEquals("", formatter.format("\\t{oo}")); + Assert.assertEquals("", formatter.format("\\d{o}")); // ??? + Assert.assertEquals("", formatter.format("\\b{o}")); // ??? + Assert.assertEquals("", formatter.format("\\aa")); // å + Assert.assertEquals("", formatter.format("\\AA")); // Å + Assert.assertEquals("", formatter.format("\\o")); // ø + Assert.assertEquals("", formatter.format("\\O")); // Ø + Assert.assertEquals("", formatter.format("\\l")); + Assert.assertEquals("", formatter.format("\\L")); + Assert.assertEquals("{\\uc2\\u223ss}", formatter.format("\\ss")); // ß + Assert.assertEquals("", formatter.format("?`")); // ¿ + Assert.assertEquals("", formatter.format("!`")); // ¡ + + Assert.assertEquals("", formatter.format("\\dag")); + Assert.assertEquals("", formatter.format("\\ddag")); + Assert.assertEquals("", formatter.format("\\S")); // § + Assert.assertEquals("", formatter.format("\\P")); // ¶ + Assert.assertEquals("", formatter.format("\\copyright")); // © + Assert.assertEquals("", formatter.format("\\pounds")); // £ } } From b0352a18f04d34fe8738d025dde1906cce220ab5 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Mon, 30 May 2016 16:31:53 +0200 Subject: [PATCH 110/268] Introduce Optional --- .../net/sf/jabref/gui/ClipBoardManager.java | 7 +- .../sf/jabref/gui/desktop/JabRefDesktop.java | 2 +- .../gui/mergeentries/MergeEntryDOIDialog.java | 6 +- .../importer/fetcher/DOItoBibTeXFetcher.java | 128 ++++++++---------- .../fileformat/PdfContentImporter.java | 4 +- .../jabref/logic/fulltext/DoiResolution.java | 2 +- .../jabref/logic/layout/format/DOICheck.java | 2 +- .../java/net/sf/jabref/logic/util/DOI.java | 2 +- .../net/sf/jabref/logic/util/DOITest.java | 16 +-- 9 files changed, 73 insertions(+), 96 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/ClipBoardManager.java b/src/main/java/net/sf/jabref/gui/ClipBoardManager.java index 2095e8123de9..fb16c131df15 100644 --- a/src/main/java/net/sf/jabref/gui/ClipBoardManager.java +++ b/src/main/java/net/sf/jabref/gui/ClipBoardManager.java @@ -32,6 +32,7 @@ import java.io.StringReader; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import net.sf.jabref.importer.fetcher.DOItoBibTeXFetcher; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -105,10 +106,8 @@ public List extractBibEntriesFromClipboard() { // fetch from doi if (DOI.build(data).isPresent()) { LOGGER.info("Found DOI in clipboard"); - BibEntry entry = new DOItoBibTeXFetcher().getEntryFromDOI(new DOI(data).getDOI()); - if (entry != null) { - result.add(entry); - } + Optional entry = new DOItoBibTeXFetcher().getEntryFromDOI(new DOI(data).getDOI()); + entry.ifPresent(result::add); } else { // parse bibtex string BibtexParser bp = new BibtexParser(new StringReader(data)); diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index c6606e12a7ab..8a577b8dbadd 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -80,7 +80,7 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, String } else if ("doi".equals(fieldName)) { Optional doiUrl = DOI.build(link); if (doiUrl.isPresent()) { - link = doiUrl.get().getURLAsASCIIString(); + link = doiUrl.get().getURIAsASCIIString(); } // should be opened in browser fieldName = "url"; diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java index 1f98aab4ecee..b3df25b126a0 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java @@ -40,9 +40,7 @@ import com.jgoodies.forms.layout.RowSpec; /** - * @author Oscar - * - * Dialog for merging Bibtex entry with data fetched from DOI + * Dialog for merging Bibtex entry with data fetched from DOI */ public class MergeEntryDOIDialog extends JDialog { @@ -72,7 +70,7 @@ public MergeEntryDOIDialog(BasePanel panel) { this.originalEntry = panel.getSelectedEntries().get(0); panel.output(Localization.lang("Fetching info based on DOI")); - this.doiEntry = doiFetcher.getEntryFromDOI(this.originalEntry.getField("doi")); + this.doiEntry = doiFetcher.getEntryFromDOI(this.originalEntry.getField("doi")).orElse(null); if (this.doiEntry == null) { panel.output(""); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index be06dacf3c67..5ad05a0eb65b 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -1,25 +1,8 @@ -/* Copyright (C) 2014 JabRef contributors. - Copyright (C) 2015 Oliver Kopp - - 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 3 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, see . - */ package net.sf.jabref.importer.fetcher; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Optional; @@ -49,24 +32,21 @@ public class DOItoBibTeXFetcher implements EntryFetcher { private final ProtectTermsFormatter protectTermsFormatter = new ProtectTermsFormatter(); private final UnitsToLatexFormatter unitsToLatexFormatter = new UnitsToLatexFormatter(); - @Override public void stopFetching() { - // nothing needed as the fetching is a single HTTP GET + // not needed as the fetching is a single HTTP GET } @Override public boolean processQuery(String query, ImportInspector inspector, OutputPrinter status) { ParserResult parserResult = new ParserResult(); - BibEntry entry = getEntryFromDOI(query, parserResult); - if(parserResult.hasWarnings()) { + Optional entry = getEntryFromDOI(query, parserResult); + if (parserResult.hasWarnings()) { status.showMessage(parserResult.getErrorMessage()); } - if (entry != null) { - inspector.addEntry(entry); - return true; - } - return false; + entry.ifPresent(e -> inspector.addEntry(e)); + + return entry.isPresent(); } @Override @@ -85,73 +65,73 @@ public JPanel getOptionsPanel() { return null; } - public BibEntry getEntryFromDOI(String doiStr) { + public Optional getEntryFromDOI(String doiStr) { return getEntryFromDOI(doiStr, null); } - public BibEntry getEntryFromDOI(String doiStr, ParserResult parserResult) { - DOI doi; - try { - doi = new DOI(doiStr); - } catch (IllegalArgumentException e) { + public Optional getEntryFromDOI(String doiStr, ParserResult parserResult) { + Optional doi = DOI.build(doiStr); + + if (!doi.isPresent()) { if (parserResult != null) { parserResult.addWarning(Localization.lang("Invalid DOI: '%0'.", doiStr)); } - return null; + return Optional.empty(); } - // Send the request - - // construct URL - URL url; try { - Optional uri = doi.getURI(); - if (uri.isPresent()) { - url = uri.get().toURL(); - } else { - return null; + URL doiURL = new URL(doi.get().getURIAsASCIIString()); + + // BibTeX data + URLDownload download = new URLDownload(doiURL); + download.addParameters("Accept", "application/x-bibtex"); + String bibtexString = download.downloadToString(StandardCharsets.UTF_8); + bibtexString = cleanupEncoding(bibtexString); + + // BibTeX entry + BibEntry entry = BibtexParser.singleFromString(bibtexString); + + if (entry == null) { + return Optional.empty(); } - } catch (MalformedURLException e) { - LOGGER.warn("Bad URL", e); - return null; - } + // Optionally re-format BibTeX entry + formatTitleField(entry); - String bibtexString = ""; - try { - URLDownload dl = new URLDownload(url); - dl.addParameters("Accept", "application/x-bibtex"); - bibtexString = dl.downloadToString(StandardCharsets.UTF_8); + return Optional.of(entry); + } catch (MalformedURLException e) { + LOGGER.warn("Bad DOI URL", e); + return Optional.empty(); } catch (FileNotFoundException e) { if (parserResult != null) { - parserResult.addWarning(Localization.lang("Unknown DOI: '%0'.", doi.getDOI())); + parserResult.addWarning(Localization.lang("Unknown DOI: '%0'.", doi.get().getDOI())); } LOGGER.debug("Unknown DOI", e); - return null; + return Optional.empty(); } catch (IOException e) { LOGGER.warn("Communication problems", e); - return null; + return Optional.empty(); } + } + + private void formatTitleField(BibEntry entry) { + // Optionally add curly brackets around key words to keep the case + entry.getFieldOptional("title").ifPresent(title -> { + // Unit formatting + if (Globals.prefs.getBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH)) { + title = unitsToLatexFormatter.format(title); + } - //Usually includes an en-dash in the page range. Char is in cp1252 but not + // Case keeping + if (Globals.prefs.getBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH)) { + title = protectTermsFormatter.format(title); + } + entry.setField("title", title); + }); + } + + private String cleanupEncoding(String bibtex) { + // Usually includes an en-dash in the page range. Char is in cp1252 but not // ISO 8859-1 (which is what latex expects). For convenience replace here. - bibtexString = bibtexString.replaceAll("(pages=\\{[0-9]+)\u2013([0-9]+\\})", "$1--$2"); - BibEntry entry = BibtexParser.singleFromString(bibtexString); - - if (entry != null) { - // Optionally add curly brackets around key words to keep the case - entry.getFieldOptional("title").ifPresent(title -> { - // Unit formatting - if (Globals.prefs.getBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH)) { - title = unitsToLatexFormatter.format(title); - } - - // Case keeping - if (Globals.prefs.getBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH)) { - title = protectTermsFormatter.format(title); - } - entry.setField("title", title); - }); - } - return entry; + return bibtex.replaceAll("(pages=\\{[0-9]+)\u2013([0-9]+\\})", "$1--$2"); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index a9a412ee9755..08a885699835 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -199,8 +199,8 @@ public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { Optional doi = DOI.findInText(firstPageContents); if (doi.isPresent()) { ParserResult parserResult = new ParserResult(result); - BibEntry entry = DOI_TO_BIBTEX_FETCHER.getEntryFromDOI(doi.get().getDOI(), parserResult); - parserResult.getDatabase().insertEntry(entry); + Optional entry = DOI_TO_BIBTEX_FETCHER.getEntryFromDOI(doi.get().getDOI(), parserResult); + entry.ifPresent(e -> parserResult.getDatabase().insertEntry(e)); return parserResult; } diff --git a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java index 0ee73cfa7aab..f4e3098fe758 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java @@ -48,7 +48,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional doi = DOI.build(entry.getField("doi")); if(doi.isPresent()) { - String sciLink = doi.get().getURLAsASCIIString(); + String sciLink = doi.get().getURIAsASCIIString(); // follow all redirects and scan for a single pdf link if (!sciLink.isEmpty()) { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/DOICheck.java b/src/main/java/net/sf/jabref/logic/layout/format/DOICheck.java index d3c9d22cc4f1..4ac3f9ce7c3e 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/DOICheck.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/DOICheck.java @@ -33,6 +33,6 @@ public String format(String fieldText) { if (result.startsWith("/")) { result = result.substring(1); } - return DOI.build(result).map(DOI::getURLAsASCIIString).orElse(result); + return DOI.build(result).map(DOI::getURIAsASCIIString).orElse(result); } } diff --git a/src/main/java/net/sf/jabref/logic/util/DOI.java b/src/main/java/net/sf/jabref/logic/util/DOI.java index 55cbfc614f1f..08814fa5f446 100644 --- a/src/main/java/net/sf/jabref/logic/util/DOI.java +++ b/src/main/java/net/sf/jabref/logic/util/DOI.java @@ -163,7 +163,7 @@ public Optional getURI() { * * @return an encoded URL representation of the DOI */ - public String getURLAsASCIIString() { + public String getURIAsASCIIString() { return getURI().map(URI::toASCIIString).orElse(""); } } diff --git a/src/test/java/net/sf/jabref/logic/util/DOITest.java b/src/test/java/net/sf/jabref/logic/util/DOITest.java index 859905ca87aa..b679ca56854f 100644 --- a/src/test/java/net/sf/jabref/logic/util/DOITest.java +++ b/src/test/java/net/sf/jabref/logic/util/DOITest.java @@ -95,23 +95,23 @@ public void correctlyDecodeHttpDOIs() { public void correctlyEncodeDOIs() { // See http://www.doi.org/doi_handbook/2_Numbering.html#2.5.2.4 // % -> (%25) - Assert.assertEquals("http://doi.org/10.1006/rwei.1999%25.0001", new DOI("http://doi.org/10.1006/rwei.1999%25.0001").getURLAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1006/rwei.1999%25.0001", new DOI("http://doi.org/10.1006/rwei.1999%25.0001").getURIAsASCIIString()); // " -> (%22) - Assert.assertEquals("http://doi.org/10.1006/rwei.1999%22.0001", new DOI("http://doi.org/10.1006/rwei.1999%22.0001").getURLAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1006/rwei.1999%22.0001", new DOI("http://doi.org/10.1006/rwei.1999%22.0001").getURIAsASCIIString()); // # -> (%23) - Assert.assertEquals("http://doi.org/10.1006/rwei.1999%23.0001", new DOI("http://doi.org/10.1006/rwei.1999%23.0001").getURLAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1006/rwei.1999%23.0001", new DOI("http://doi.org/10.1006/rwei.1999%23.0001").getURIAsASCIIString()); // SPACE -> (%20) - Assert.assertEquals("http://doi.org/10.1006/rwei.1999%20.0001", new DOI("http://doi.org/10.1006/rwei.1999%20.0001").getURLAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1006/rwei.1999%20.0001", new DOI("http://doi.org/10.1006/rwei.1999%20.0001").getURIAsASCIIString()); // ? -> (%3F) - Assert.assertEquals("http://doi.org/10.1006/rwei.1999%3F.0001", new DOI("http://doi.org/10.1006/rwei.1999%3F.0001").getURLAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1006/rwei.1999%3F.0001", new DOI("http://doi.org/10.1006/rwei.1999%3F.0001").getURIAsASCIIString()); } @Test public void constructCorrectURLForDoi() { // add / to RESOLVER url if missing - Assert.assertEquals("http://doi.org/10.1006/jmbi.1998.2354", new DOI("10.1006/jmbi.1998.2354").getURLAsASCIIString()); - Assert.assertEquals("http://doi.org/10.1006/jmbi.1998.2354", new DOI("http://doi.org/10.1006/jmbi.1998.2354").getURLAsASCIIString()); - Assert.assertEquals("http://doi.org/10.1109/VLHCC.2004.20", new DOI("doi:10.1109/VLHCC.2004.20").getURLAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1006/jmbi.1998.2354", new DOI("10.1006/jmbi.1998.2354").getURIAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1006/jmbi.1998.2354", new DOI("http://doi.org/10.1006/jmbi.1998.2354").getURIAsASCIIString()); + Assert.assertEquals("http://doi.org/10.1109/VLHCC.2004.20", new DOI("doi:10.1109/VLHCC.2004.20").getURIAsASCIIString()); } @Test From 62855516d513e252051f683179598b7a8399af86 Mon Sep 17 00:00:00 2001 From: Christian Bartsch Date: Mon, 23 May 2016 14:01:25 +0200 Subject: [PATCH 111/268] entry retains its groupmembership when cut/deletion is undone --- CHANGELOG.md | 1 + .../net/sf/jabref/event/EntryAddedEvent.java | 40 +++++++++++++++++-- .../java/net/sf/jabref/gui/BasePanel.java | 6 +++ .../jabref/gui/undo/UndoableRemoveEntry.java | 2 +- .../sf/jabref/model/database/BibDatabase.java | 17 +++++++- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a74ad6665a6..0fee1633fab7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#651](https://github.com/JabRef/jabref/issues/651): Improve parsing of author names containing braces - Fixed [#1421](https://github.com/JabRef/jabref/issues/1421): Auto downloader should try to retrieve DOI if not present and fetch afterwards - Fixed [#1457](https://github.com/JabRef/jabref/issues/1457): Support multiple words inside LaTeX commands to RTF export +- Entries retain their groupmembership when undoing their cut/deletion ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/event/EntryAddedEvent.java b/src/main/java/net/sf/jabref/event/EntryAddedEvent.java index 13e23b637296..82682d17d319 100644 --- a/src/main/java/net/sf/jabref/event/EntryAddedEvent.java +++ b/src/main/java/net/sf/jabref/event/EntryAddedEvent.java @@ -1,19 +1,51 @@ +/* Copyright (C) 2016 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.event; +import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; /** - * EntryAddedEvent is fired when a new BibEntry was added - * to the database. + * {@link EntryAddedEvent} is fired when a new {@link BibEntry} was added to the {@link BibDatabase}. */ - public class EntryAddedEvent extends EntryEvent { /** - * @param bibEntry BibEntry object which has been added. + * flag if the addition is the undo of a deletion/cut + */ + private boolean isUndo; + + /** + * @param bibEntry the entry which has been added */ public EntryAddedEvent(BibEntry bibEntry) { super(bibEntry); + this.isUndo = false; } + /** + * @param bibEntry the entry which has been added + * @param isUndo flag if the addition is the undo of a deletion/cut + */ + public EntryAddedEvent(BibEntry bibEntry, boolean isUndo) { + super(bibEntry); + this.isUndo = isUndo; + } + + public boolean isUndo() { + return isUndo; + } } diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index a9b158f1cf9c..2ad22b761f11 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -1269,6 +1269,12 @@ public void run() { @Subscribe public void listen(EntryAddedEvent addedEntryEvent) { + // if the added entry is an undo don't add it to the current group + if (addedEntryEvent.isUndo()){ + scheduleUpdate(); + return; + } + // Automatically add new entry to the selected group (or set of groups) if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP) && frame.groupToggle.isSelected()) { final List entries = Collections.singletonList(addedEntryEvent.getBibEntry()); diff --git a/src/main/java/net/sf/jabref/gui/undo/UndoableRemoveEntry.java b/src/main/java/net/sf/jabref/gui/undo/UndoableRemoveEntry.java index 2902807feca1..0747f87116f4 100644 --- a/src/main/java/net/sf/jabref/gui/undo/UndoableRemoveEntry.java +++ b/src/main/java/net/sf/jabref/gui/undo/UndoableRemoveEntry.java @@ -58,7 +58,7 @@ public String getRedoPresentationName() { @Override public void undo() { super.undo(); - base.insertEntry(entry); + base.insertEntry(entry, true); } @Override diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index f4c4e7464555..6b8c82b10f3d 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -175,9 +175,24 @@ public synchronized List getEntriesByKey(String key) { * Inserts the entry, given that its ID is not already in use. * use Util.createId(...) to make up a unique ID for an entry. * + * @param entry the entry to insert into the database * @return false if the insert was done without a duplicate warning + * @throws KeyCollisionException thrown if the entry id ({@link BibEntry#getId()}) is already present in the database */ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionException { + return this.insertEntry(entry, false); + } + + /** + * Inserts the entry, given that its ID is not already in use. + * use Util.createId(...) to make up a unique ID for an entry. + * + * @param entry the entry to insert into the database + * @param isUndo set to true if the insertion is caused by an undo + * @return false if the insert was done without a duplicate warning + * @throws KeyCollisionException thrown if the entry id ({@link BibEntry#getId()}) is already present in the database + */ + public synchronized boolean insertEntry(BibEntry entry, boolean isUndo) throws KeyCollisionException { Objects.requireNonNull(entry); String id = entry.getId(); @@ -189,7 +204,7 @@ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionExcep entries.add(entry); entry.registerListener(this); - eventBus.post(new EntryAddedEvent(entry)); + eventBus.post(new EntryAddedEvent(entry, isUndo)); return duplicationChecker.checkForDuplicateKeyAndAdd(null, entry.getCiteKey()); } From 623f8e60fff0d79425ca206ff6947dca6ab2ae49 Mon Sep 17 00:00:00 2001 From: matthiasgeiger Date: Tue, 31 May 2016 11:51:00 +0200 Subject: [PATCH 112/268] set splitPane size before (re)creating maintable - fixes #1450 --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/BasePanel.java | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fee1633fab7..b75d8828dc9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1421](https://github.com/JabRef/jabref/issues/1421): Auto downloader should try to retrieve DOI if not present and fetch afterwards - Fixed [#1457](https://github.com/JabRef/jabref/issues/1457): Support multiple words inside LaTeX commands to RTF export - Entries retain their groupmembership when undoing their cut/deletion +- Fixed [#1450](https://github.com/JabRef/jabref/issues/1450): EntryEditor is restored in the correct size after preference changes ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 2ad22b761f11..2435f909c95b 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -1518,6 +1518,7 @@ public void keyPressed(KeyEvent e) { public void setupMainPanel() { splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); splitPane.setDividerSize(SPLIT_PANE_DIVIDER_SIZE); + adjustSplitter(); // restore last splitting state (before mainTable is created as creation affects the stored size of the entryEditors) // check whether a mainTable already existed and a floatSearch was active boolean floatSearchActive = (mainTable != null) && (this.tableModel.getSearchState() == MainTableDataModel.DisplayOption.FLOAT); From 1e7be4978e27e6393893e29489276e17cde98bdb Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Tue, 31 May 2016 15:10:14 +0200 Subject: [PATCH 113/268] Improve DOI fetcher accuracy even more as long as we don't have a LaTeX-free version #1424 --- .../net/sf/jabref/importer/fetcher/CrossRef.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java index 14fd6970b609..f539c9a3f878 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java @@ -5,6 +5,7 @@ import java.util.Optional; import net.sf.jabref.logic.formatter.bibtexfields.RemoveBracesFormatter; +import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; @@ -81,7 +82,8 @@ private static String enhanceQuery(String query, BibEntry entry) { } private static boolean checkValidity(BibEntry entry, JSONArray result) { - final String entryTitle = new RemoveBracesFormatter().format(entry.getField("title")); + // TODO: use latex-free version instead in the future + final String entryTitle = removeLaTeX(entry.getField("title")); // currently only title-based // title: [ "How the Mind Hurts and Heals the Body." ] @@ -109,7 +111,18 @@ private static boolean checkValidity(BibEntry entry, JSONArray result) { } } + private static String removeLaTeX(String text) { + String result; + // remove braces + result = new RemoveBracesFormatter().format(text); + // convert to unicode + result = new LatexToUnicodeFormatter().format(result); + + return result; + } + private static double editDistanceIgnoreCase(String a, String b) { + // TODO: locale is dependent on the language of the strings?! return METRIC_DISTANCE.distance(a.toLowerCase(Locale.ENGLISH), b.toLowerCase(Locale.ENGLISH)); } } From bd7e23f13e109342bad103ccabd5a8305b033494 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 1 Jun 2016 10:27:02 +0200 Subject: [PATCH 114/268] Some more Swedish translations (#1468) --- src/main/resources/l10n/JabRef_sv.properties | 58 ++++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 1563e3352d4b..2d3704560211 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1,19 +1,19 @@ # Swedish translation of JabRef -%0_contains_the_regular_expression_%1= +%0_contains_the_regular_expression_%1=%0_innehåller_det_reguljära_uttrycket_%1 %0_contains_the_term_%1=%0_innehåller_termen_%1 %0_databases_will_be_imported=%0_databaser_kommer_att_importeras -%0_doesn't_contain_the_regular_expression_%1= +%0_doesn't_contain_the_regular_expression_%1=%0_innehåller_inte_det_reguljära_uttrycket_%1 %0_doesn't_contain_the_term_%1=%0_innehåller_inte_termen_%1 %0_entries_found._To_reduce_server_load,_only_%1_will_be_downloaded.=%0_poster_hittades._För_att_minska_lasten_på_servern_kommer_bara_%1_att_laddas_ned. %0_entries_needed_a_clean_up=%0_poster_behövde_städas_upp %0_export_successful=%0-export_lyckades %0_image=%0-bild -%0_matches_the_regular_expression_%1= +%0_matches_the_regular_expression_%1=%0_matchar_det_reguljära_uttrycket_%1 %0_matches_the_term_%1=%0_matchar_termen_%1 %0_mode=%0-läge %0_problem(s)_found=%0_problem_hittades '%0'_exists._Overwrite_file?='%0'_finns_redan._Skriv_över_filen? -'%0'_is_not_a_valid_ADS_bibcode.= +'%0'_is_not_a_valid_ADS_bibcode.='%0'_är_inte_en_giltig_ADS-bibkod. Could_not_find_file_'%0'
    linked_from_entry_'%1'=Hittar_inte_filen_'%0'
    som_länkas_från_posten_'%1' = <_CREATE_NEW_DATABASE_>=<_SKAPA_NY_DATABAS_> @@ -34,8 +34,8 @@ About_JabRef=Om_JabRef Abstract=Sammanfattning Accept=Acceptera Accept_change=Acceptera_ändring -Accepting_the_change_replaces_the_complete_groups_tree_with_the_externally_modified_groups_tree.= -Action= +Accepting_the_change_replaces_the_complete_groups_tree_with_the_externally_modified_groups_tree.=Om_ändringarna_accepteras_så_kommer_hela_gruppträdet_att_ersättas_av_det_externt_ändrade_gruppträdet. +Action=Händelse Add=Lägg_till Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.= Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path.= @@ -69,7 +69,7 @@ Always_add_letter_(a,_b,_...)_to_generated_keys=Lägg_alltid_till_en_bokstav_(a, Always_reformat_.bib_file_on_save_and_export=Formattera_allid_om_.bib-filen_vid_när_den_sparas_eller_exporteras Always_use_this_PDF_import_style_(and_do_not_ask_for_each_import)= An_Error_occurred_while_fetching_from_ADS_(%0)\:= -An_Error_occurred_while_parsing_abstract= +An_Error_occurred_while_parsing_abstract=Ett_fel_inträffade_när_sammanfattningen_tolkades An_Exception_occurred_while_accessing_'%0'= An_SAXException_occurred_while_parsing_'%0'\:= An_autosave_file_was_found_for_this_database._This_could_indicate_that_JabRef_didn't_shut_down_cleanly_last_time_the_file_was_used.= @@ -80,21 +80,21 @@ Append_database=Lägg_till_databas Append_the_selected_text_to_BibTeX_field=Lägg_till_vald_text_till_BibTeX-nyckeln Application=Program Apply=Tillämpa -Are_you_sure_you_want_to_remove_the_already_existent_SQL_DBs?= +Are_you_sure_you_want_to_remove_the_already_existent_SQL_DBs?=Är_du_säker_att_du_vill_ta_bort_den_befintliga_SQL-databasen? Are_you_sure_you_want_to_reset_all_settings_to_default_values?=Är_du_säker_att_du_vill_återställa_alla_inställningar_till_standardvärden? -Arguments_passed_on_to_running_JabRef_instance._Shutting_down.= +Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumenten_skickades_till_JabRef-instansen_som_redan_kördes._Stänger_ned. Assign_entry_selection_exclusively_to_this_group= -Assign_new_file= -Assign_the_original_group's_entries_to_this_group?= -Assigned_%0_entries_to_group_"%1".= -Assigned_1_entry_to_group_"%0".= +Assign_new_file=Tilldela_ny_fil +Assign_the_original_group's_entries_to_this_group?=Tilldela_den_ursprungliga_gruppens_poster_till_denna_grupp? +Assigned_%0_entries_to_group_"%1".=Tilldelade_%0_poster_till_gruppen_"%1". +Assigned_1_entry_to_group_"%0".=Tilldelade_en_post_till_gruppen_"%0". Attach_URL=Lägg_till_URL Attach_file=Lägg_till_fil Attempt_to_automatically_set_file_links_for_your_entries._Automatically_setting_works_if_a_file_in_your_file_directory
    or_a_subdirectory_is_named_identically_to_an_entry's_BibTeX_key,_plus_extension.= Attempting_SQL_export...=Försöker_SQL-export Attempting_SQL_import...=Försöker_SQL-import Attention\:_Password_is_stored_in_plain_text\!=OBS\!_Lösenordet_sparas_i_klartext\! -Auto-generating_PDF-Names_does_not_support_undo._Continue?= +Auto-generating_PDF-Names_does_not_support_undo._Continue?=Du_kan_inte_ångra_automatisk_generering_av_PDF-namn._Fortsätt? Auto=Automatiskt Autocomplete_after_following_number_of_characters=Komplettera_automatiskt_efter_följande_antal_bokstäver Autocomplete_names_in_'Firstname_Lastname'_format_only=Komplettera_enbart_namn_i_'Förnamn_Efternamn'-format @@ -598,7 +598,7 @@ Importing=Importerar Importing_canceled= Importing_in_unknown_format=Importerar_i_okänt_format Importing_into_Database...=Importerar_till_databas... -Include_abstracts= +Include_abstracts=Inkludera_sammanfattning Include_entries=Inkludera_poster Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups= Increase_table_font_size=Öka_typsnittsstorlek_för_tabellen @@ -1381,7 +1381,7 @@ paste_entry=klistra_in_post paste_text_here=klistra_in_text_här plain_text=klartext refines_supergroup= -regular_expression= +regular_expression=reguljärt_uttryck remove_group_(keep_subgroups)=ta_bort_grupp_(behåll_undergrupper) remove_group_and_subgroups=ta_bort_grupp_och_undergrupper remove_string=ta_bort_sträng @@ -1402,7 +1402,7 @@ unexpected_closing_curly_bracket=oväntad_avslutande_måsvinge unexpected_opening_curly_bracket=oväntad_startande_måsvinge unknown_edit=okänd_ändring untitled=namnlös -usage= +usage=användning value=värde verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid= web_link=weblänk @@ -1447,7 +1447,7 @@ Protect_terms=Skydda_termer Remove_enclosing_braces=Ta_bort_inneslutande_måsvingar Removes_braces_encapsulating_the_complete_field_content.=Ta_bort_måsvingar_som_innesluter_hela_fältet. Sentence_case= -Shortens_lists_of_persons_if_there_are_more_than_2_persons_to_"et_al.".=Kortar_av_personlistor_om_det_är_fler_än_namn_till_"et_al."y +Shortens_lists_of_persons_if_there_are_more_than_2_persons_to_"et_al.".=Kortar_av_personlistor_om_det_är_fler_än_namn_till_"et_al." Title_case= Unicode_to_LaTeX=Unicode_till_LaTeX Units_to_LaTeX=Enheter_till_LaTeX @@ -1525,24 +1525,24 @@ Show_symmetric_diff=Visa_skillnad_symmetriskt booktitle_ends_with_'conference_on'= HTML_encoded_character_found=HTML-kodade_tecken_hittades -All_external_files= +All_external_files=Alla_externa_filer -OpenOffice/LibreOffice_integration= +OpenOffice/LibreOffice_integration=OpenOffice/LibreOffice-integration -incorrect_control_digit= -incorrect_format= +incorrect_control_digit=felaktig_kontrollsiffra +incorrect_format=felaktigit_format -Expected_"%0"_to_contain_whitespace= +Expected_"%0"_to_contain_whitespace=Förväntade_"%0"_att_innehålla_mellanslag Syntax_error_in_regular-expression_pattern= -Copy_version_to_clipboard= -Copied_version_to_clipboard= +Copy_version_to_clipboard=Kopiera_version_till_urklipp +Copied_version_to_clipboard=Kopierade_version_till_urklipp -BibTeX_key= -Message= +BibTeX_key=BibTeX-nyckel +Message=Meddelande Get_fulltext= +Download_from_URL=Ladda_ned_från_URL +Decryption_not_supported.=Avkryptering_stöds_ej. -Download_from_URL= -Decryption_not_supported.= From 7d034d1580cdca7acd00c1ee31646643b3e5677e Mon Sep 17 00:00:00 2001 From: Matthias Geiger Date: Thu, 2 Jun 2016 16:02:42 +0200 Subject: [PATCH 115/268] Add missing status translations for various specialfields (#1466) * add missing status translations for various specialfields * add previously existing translations for ASCII and real unicode files * readd previously existing translation * fix NPE and reduce number of needed translations by using params * improve understandability of getTextDone() --- .../java/net/sf/jabref/gui/BasePanel.java | 7 ++-- .../net/sf/jabref/specialfields/Printed.java | 16 +++----- .../net/sf/jabref/specialfields/Priority.java | 13 ++---- .../net/sf/jabref/specialfields/Quality.java | 16 +++----- .../net/sf/jabref/specialfields/Rank.java | 11 +---- .../sf/jabref/specialfields/ReadStatus.java | 12 ++---- .../sf/jabref/specialfields/Relevance.java | 16 +++----- .../sf/jabref/specialfields/SpecialField.java | 41 ++++++++++++++++--- .../specialfields/SpecialFieldAction.java | 21 ++++------ .../specialfields/SpecialFieldValue.java | 3 +- src/main/resources/l10n/JabRef_da.properties | 7 ++-- src/main/resources/l10n/JabRef_de.properties | 7 ++-- src/main/resources/l10n/JabRef_en.properties | 7 ++-- src/main/resources/l10n/JabRef_es.properties | 7 ++-- src/main/resources/l10n/JabRef_fa.properties | 7 ++-- src/main/resources/l10n/JabRef_fr.properties | 7 ++-- src/main/resources/l10n/JabRef_in.properties | 7 ++-- src/main/resources/l10n/JabRef_it.properties | 7 ++-- src/main/resources/l10n/JabRef_ja.properties | 7 ++-- src/main/resources/l10n/JabRef_nl.properties | 7 ++-- src/main/resources/l10n/JabRef_no.properties | 7 ++-- .../resources/l10n/JabRef_pt_BR.properties | 7 ++-- src/main/resources/l10n/JabRef_ru.properties | 7 ++-- src/main/resources/l10n/JabRef_sv.properties | 7 ++-- src/main/resources/l10n/JabRef_tr.properties | 7 ++-- src/main/resources/l10n/JabRef_vi.properties | 7 ++-- src/main/resources/l10n/JabRef_zh.properties | 7 ++-- 27 files changed, 138 insertions(+), 137 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 2435f909c95b..7445502a3d6b 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -963,15 +963,14 @@ public void update() { actions.put(Relevance.getInstance().getValues().get(0).getActionName(), new SpecialFieldAction(frame, Relevance.getInstance(), Relevance.getInstance().getValues().get(0).getFieldValue().get(), true, - Localization.lang("Toggle relevance"), Localization.lang("Toggled relevance for %0 entries"))); + Localization.lang("Toggle relevance"))); actions.put(Quality.getInstance().getValues().get(0).getActionName(), new SpecialFieldAction(frame, Quality.getInstance(), Quality.getInstance().getValues().get(0).getFieldValue().get(), true, - Localization.lang("Toggle quality assured"), - Localization.lang("Toggled quality for %0 entries"))); + Localization.lang("Toggle quality assured"))); actions.put(Printed.getInstance().getValues().get(0).getActionName(), new SpecialFieldAction(frame, Printed.getInstance(), Printed.getInstance().getValues().get(0).getFieldValue().get(), true, - Localization.lang("Toggle print status"), Localization.lang("Toggled print status for %0 entries"))); + Localization.lang("Toggle print status"))); for (SpecialFieldValue prio : Priority.getInstance().getValues()) { actions.put(prio.getActionName(), prio.getAction(this.frame)); diff --git a/src/main/java/net/sf/jabref/specialfields/Printed.java b/src/main/java/net/sf/jabref/specialfields/Printed.java index 109172258b58..dce2050a7915 100644 --- a/src/main/java/net/sf/jabref/specialfields/Printed.java +++ b/src/main/java/net/sf/jabref/specialfields/Printed.java @@ -34,7 +34,6 @@ private Printed() { values.add(new SpecialFieldValue(this, "printed", "togglePrinted", Localization.lang("Toggle print status"), IconTheme.JabRefIcon.PRINTED.getSmallIcon(), Localization.lang("Toggle print status"))); this.setValues(values); - TEXT_DONE_PATTERN = "Toggled print status for %0 entries"; } @Override @@ -42,6 +41,11 @@ public String getFieldName() { return SpecialFieldsUtils.FIELDNAME_PRINTED; } + @Override + public String getLocalizedFieldName() { + return Localization.lang("Printed"); + } + public static Printed getInstance() { if (Printed.INSTANCE == null) { Printed.INSTANCE = new Printed(); @@ -54,16 +58,6 @@ public Icon getRepresentingIcon() { return this.getValues().get(0).getIcon(); } - @Override - public String getToolTip() { - return this.getValues().get(0).getToolTipText(); - } - - @Override - public String getMenuString() { - return Localization.lang("Printed"); - } - @Override public boolean isSingleValueField() { return true; diff --git a/src/main/java/net/sf/jabref/specialfields/Priority.java b/src/main/java/net/sf/jabref/specialfields/Priority.java index 798226bb1eb1..0d18ed2baddf 100644 --- a/src/main/java/net/sf/jabref/specialfields/Priority.java +++ b/src/main/java/net/sf/jabref/specialfields/Priority.java @@ -46,7 +46,6 @@ private Priority() { values.add(new SpecialFieldValue(this, "prio3", "setPriority3", Localization.lang("Set priority to low"), tmpicon, Localization.lang("Priority low"))); this.setValues(values); - TEXT_DONE_PATTERN = "Set priority to '%0' for %1 entries"; } public static Priority getInstance() { @@ -61,18 +60,12 @@ public String getFieldName() { return SpecialFieldsUtils.FIELDNAME_PRIORITY; } - @Override - public Icon getRepresentingIcon() { - return this.icon; - } - - @Override - public String getToolTip() { + @Override public String getLocalizedFieldName() { return Localization.lang("Priority"); } @Override - public String getMenuString() { - return Localization.lang("Priority"); + public Icon getRepresentingIcon() { + return this.icon; } } diff --git a/src/main/java/net/sf/jabref/specialfields/Quality.java b/src/main/java/net/sf/jabref/specialfields/Quality.java index 7bd4b482bf40..8467540137c8 100644 --- a/src/main/java/net/sf/jabref/specialfields/Quality.java +++ b/src/main/java/net/sf/jabref/specialfields/Quality.java @@ -35,7 +35,6 @@ private Quality() { Localization.lang("Toggle quality assured"), IconTheme.JabRefIcon.QUALITY_ASSURED.getSmallIcon(), Localization.lang("Toggle quality assured"))); this.setValues(values); - TEXT_DONE_PATTERN = "Toggled quality for %0 entries"; } @Override @@ -43,6 +42,11 @@ public String getFieldName() { return SpecialFieldsUtils.FIELDNAME_QUALITY; } + @Override + public String getLocalizedFieldName() { + return Localization.lang("Quality"); + } + public static Quality getInstance() { if (Quality.INSTANCE == null) { Quality.INSTANCE = new Quality(); @@ -55,16 +59,6 @@ public Icon getRepresentingIcon() { return IconTheme.JabRefIcon.QUALITY.getSmallIcon(); } - @Override - public String getToolTip() { - return this.getValues().get(0).getToolTipText(); - } - - @Override - public String getMenuString() { - return Localization.lang("Quality"); - } - @Override public boolean isSingleValueField() { return true; diff --git a/src/main/java/net/sf/jabref/specialfields/Rank.java b/src/main/java/net/sf/jabref/specialfields/Rank.java index 115a15b4fade..2dbb82a6b7b2 100644 --- a/src/main/java/net/sf/jabref/specialfields/Rank.java +++ b/src/main/java/net/sf/jabref/specialfields/Rank.java @@ -28,8 +28,6 @@ public class Rank extends SpecialField { private static Rank INSTANCE; private Rank() { - TEXT_DONE_PATTERN = "Set rank to '%0' for %1 entries"; - List values = new ArrayList<>(); // lab.setName("i"); values.add(new SpecialFieldValue(this, null, "clearRank", Localization.lang("Clear rank"), null, @@ -60,14 +58,7 @@ public String getFieldName() { return SpecialFieldsUtils.FIELDNAME_RANKING; } - @Override - public String getToolTip() { + @Override public String getLocalizedFieldName() { return Localization.lang("Rank"); } - - @Override - public String getMenuString() { - return Localization.lang("Rank"); - } - } diff --git a/src/main/java/net/sf/jabref/specialfields/ReadStatus.java b/src/main/java/net/sf/jabref/specialfields/ReadStatus.java index 8bb316b69f19..82994594b7bc 100644 --- a/src/main/java/net/sf/jabref/specialfields/ReadStatus.java +++ b/src/main/java/net/sf/jabref/specialfields/ReadStatus.java @@ -45,7 +45,6 @@ private ReadStatus() { Localization.lang("Set read status to skimmed"), tmpicon, Localization.lang("Read status skimmed"))); this.setValues(values); - TEXT_DONE_PATTERN = "Set read status to '%0' for %1 entries"; } public static ReadStatus getInstance() { @@ -61,17 +60,12 @@ public String getFieldName() { } @Override - public Icon getRepresentingIcon() { - return this.icon; - } - - @Override - public String getToolTip() { + public String getLocalizedFieldName() { return Localization.lang("Read status"); } @Override - public String getMenuString() { - return Localization.lang("Read status"); + public Icon getRepresentingIcon() { + return this.icon; } } diff --git a/src/main/java/net/sf/jabref/specialfields/Relevance.java b/src/main/java/net/sf/jabref/specialfields/Relevance.java index d5791f5f9ea1..82e86a83f295 100644 --- a/src/main/java/net/sf/jabref/specialfields/Relevance.java +++ b/src/main/java/net/sf/jabref/specialfields/Relevance.java @@ -35,7 +35,6 @@ private Relevance() { values.add(new SpecialFieldValue(this, "relevant", "toggleRelevance", Localization.lang("Toggle relevance"), IconTheme.JabRefIcon.RELEVANCE.getSmallIcon(), Localization.lang("Toggle relevance"))); this.setValues(values); - TEXT_DONE_PATTERN = "Toggled relevance for %0 entries"; } @Override @@ -43,6 +42,11 @@ public String getFieldName() { return SpecialFieldsUtils.FIELDNAME_RELEVANCE; } + @Override + public String getLocalizedFieldName() { + return Localization.lang("Relevance"); + } + public static Relevance getInstance() { if (Relevance.INSTANCE == null) { Relevance.INSTANCE = new Relevance(); @@ -55,16 +59,6 @@ public Icon getRepresentingIcon() { return this.getValues().get(0).getIcon(); } - @Override - public String getToolTip() { - return this.getValues().get(0).getToolTipText(); - } - - @Override - public String getMenuString() { - return Localization.lang("Relevance"); - } - @Override public boolean isSingleValueField() { return true; diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialField.java b/src/main/java/net/sf/jabref/specialfields/SpecialField.java index 0097d6712363..28c0680f83d4 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialField.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialField.java @@ -18,17 +18,22 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Objects; import javax.swing.Icon; +import net.sf.jabref.logic.l10n.Localization; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + public abstract class SpecialField { + private static final Log LOGGER = LogFactory.getLog(SpecialField.class); + // currently, menuString is used for undo string // public static String TEXT_UNDO; - // Plain string; NOT treated by Globals.lang - public String TEXT_DONE_PATTERN; - private List values; private List keywords; private HashMap map; @@ -58,11 +63,37 @@ public SpecialFieldValue parse(String s) { public abstract String getFieldName(); + public abstract String getLocalizedFieldName(); + public abstract Icon getRepresentingIcon(); - public abstract String getMenuString(); + public String getMenuString() { + return getLocalizedFieldName(); + } + + public String getToolTip() { + return getLocalizedFieldName(); + } - public abstract String getToolTip(); + public String getTextDone(String... params) { + Objects.requireNonNull(params); + + if (isSingleValueField() && (params.length == 1) && (params[0] != null)) { + // Single value fields can be toggled only + return Localization.lang("Toggled '%0' for %1 entries", getLocalizedFieldName(), params[0]); + } else if (!isSingleValueField() && (params.length == 2) && (params[0] != null) && (params[1] != null)) { + // setting a multi value special field - the setted value is displayed, too + String[] allParams = {getLocalizedFieldName(), params[0], params[1]}; + return Localization.lang("Set '%0' to '%1' for %2 entries", allParams); + } else if (!isSingleValueField() && (params.length == 1) && (params[0] != null)) { + // clearing a multi value specialfield + return Localization.lang("Cleared '%0' for %1 entries", getLocalizedFieldName(), params[0]); + } else { + // invalid usage + LOGGER.info("Creation of special field status change message failed: illegal argument combination."); + return ""; + } + } public boolean isSingleValueField() { return false; diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java index ecf17d387766..c96592111097 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java @@ -20,7 +20,6 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.BaseAction; import net.sf.jabref.gui.undo.NamedCompound; -import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import org.apache.commons.logging.Log; @@ -29,8 +28,7 @@ public class SpecialFieldAction implements BaseAction { private final JabRefFrame frame; - private final String doneTextPattern; - private final SpecialField c; + private final SpecialField specialField; private final String value; private final boolean nullFieldIfValueIsTheSame; private final String undoText; @@ -41,21 +39,18 @@ public class SpecialFieldAction implements BaseAction { /** * * @param nullFieldIfValueIsTheSame - false also causes that doneTextPattern has two place holders %0 for the value and %1 for the sum of entries - * @param doneTextPattern - the pattern to use to update status information shown in MainFrame */ public SpecialFieldAction( JabRefFrame frame, - SpecialField c, + SpecialField specialField, String value, boolean nullFieldIfValueIsTheSame, - String undoText, - String doneTextPattern) { + String undoText) { this.frame = frame; - this.c = c; + this.specialField = specialField; this.value = value; this.nullFieldIfValueIsTheSame = nullFieldIfValueIsTheSame; this.undoText = undoText; - this.doneTextPattern = doneTextPattern; } @Override @@ -68,7 +63,7 @@ public void action() { NamedCompound ce = new NamedCompound(undoText); for (BibEntry be : bes) { // if (value==null) and then call nullField has been omitted as updatefield also handles value==null - SpecialFieldsUtils.updateField(c, value, be, ce, nullFieldIfValueIsTheSame); + SpecialFieldsUtils.updateField(specialField, value, be, ce, nullFieldIfValueIsTheSame); } ce.end(); if (ce.hasEdits()) { @@ -76,10 +71,10 @@ public void action() { frame.getCurrentBasePanel().markBaseChanged(); frame.getCurrentBasePanel().updateEntryEditorIfShowing(); String outText; - if (nullFieldIfValueIsTheSame) { - outText = Localization.lang(doneTextPattern, Integer.toString(bes.size())); + if (nullFieldIfValueIsTheSame || value==null) { + outText = specialField.getTextDone(Integer.toString(bes.size())); } else { - outText = Localization.lang(doneTextPattern, value, Integer.toString(bes.size())); + outText = specialField.getTextDone(value, Integer.toString(bes.size())); } frame.output(outText); } else { diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldValue.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldValue.java index 27fa558ac595..eb1dfc88acc7 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldValue.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldValue.java @@ -107,8 +107,7 @@ public SpecialFieldAction getAction(JabRefFrame frame) { // if field contains only one value, it has to be nulled // otherwise, another setting does not empty the field this.field.getValues().size() == 1, - this.getMenuString(), - this.field.TEXT_DONE_PATTERN); + this.getMenuString()); } return action; } diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 3803774f1fad..585e1370651e 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1307,9 +1307,6 @@ Show_gridlines= Show_printed_status= Show_read_status= Table_row_height_padding= -Toggled_quality_for_%0_entries= -Toggled_print_status_for_%0_entries= -Toggled_relevance_for_%0_entries= Marked_all_%0_selected_entries= Marked_selected_entry= @@ -1687,3 +1684,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index bcfd090fadf7..fcc8d6687599 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2015,9 +2015,6 @@ Show_gridlines=Gitternetzlinien_anzeigen Show_printed_status=Druckstatus_anzeigen Show_read_status=Lesestatus_anzeigen Table_row_height_padding=Zeilenabstand -Toggled_quality_for_%0_entries=Qualität_für_%0_Einträge_umschalten -Toggled_print_status_for_%0_entries=Druckstatus_für_%0_Einträge_umschalten -Toggled_relevance_for_%0_entries=Relevanz_für_%0_Einträge_schalten Marked_all_%0_selected_entries=Alle_%0_Einträge_markiert Marked_selected_entry=Ausgewählten_Eintrag_markiert @@ -2403,3 +2400,7 @@ Get_fulltext=Hole_Volltext Download_from_URL=Download_von_URL Decryption_not_supported.=Entschlüsselung_wird_nicht_unterstützt. + +Cleared_'%0'_for_%1_entries='%0'_für_%1_Einträge_entfernt +Set_'%0'_to_'%1'_for_%2_entries='%0'_für_%2_Einträge_auf_'%1'_gesetzt +Toggled_'%0'_for_%1_entries='%0'_für_%1_Einträge_geändert \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index af02f181a467..babd36026bf9 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1921,9 +1921,6 @@ Show_gridlines=Show_gridlines Show_printed_status=Show_printed_status Show_read_status=Show_read_status Table_row_height_padding=Table_row_height_padding -Toggled_quality_for_%0_entries=Toggled_quality_for_%0_entries -Toggled_print_status_for_%0_entries=Toggled_print_status_for_%0_entries -Toggled_relevance_for_%0_entries=Toggled_relevance_for_%0_entries Marked_selected_entry=Marked_selected_entry Marked_all_%0_selected_entries=Marked_all_%0_selected_entries @@ -2259,3 +2256,7 @@ BibTeX_key=BibTeX_key Message=Message Decryption_not_supported.=Decryption_not_supported. + +Cleared_'%0'_for_%1_entries=Cleared_'%0'_for_%1_entries +Set_'%0'_to_'%1'_for_%2_entries=Set_'%0'_to_'%1'_for_%2_entries +Toggled_'%0'_for_%1_entries=Toggled_'%0'_for_%1_entries \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 02d240878c70..c1c4f1a436ac 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1208,9 +1208,6 @@ Show_gridlines=Mostrar_líneas_de_rejilla Show_printed_status=Mostrar_estatus_de_impresion Show_read_status=Mostrar_estatus_de_lectura Table_row_height_padding=Relleno_de_altura_de_fila -Toggled_quality_for_%0_entries=Cambiada_calidad_para_%0_entradas -Toggled_print_status_for_%0_entries=Cambiado_estatus_de_impresion -Toggled_relevance_for_%0_entries=Cambiada_relevancia_para_%0_entradas Marked_all_%0_selected_entries=Marcadas_todas_las_%0_entradas_seleccionadas Marked_selected_entry=Entrada_marcada_seleccionadas @@ -1588,3 +1585,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries=Ajustes_de_'%0'_para_%1_entradas +Set_'%0'_to_'%1'_for_%2_entries=Establecer_'%0'_a_'%1'_para_%2_entradas +Toggled_'%0'_for_%1_entries=Cambiada_'%0'_para_%1_entradas \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 7a87a29200c4..7f8c32fc98e0 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1970,9 +1970,6 @@ Show_gridlines= Show_printed_status= Show_read_status= Table_row_height_padding= -Toggled_quality_for_%0_entries= -Toggled_print_status_for_%0_entries= -Toggled_relevance_for_%0_entries= Marked_selected_entry= Marked_all_%0_selected_entries= @@ -2374,3 +2371,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 23479f5c6eee..9b042d726853 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1247,9 +1247,6 @@ Show_gridlines=Afficher_la_grille Show_printed_status=Afficher_le_statut_d'impression Show_read_status=Afficher_le_statut_de_lecture Table_row_height_padding=Espacement_en_hauteur_des_rangées_de_tableau -Toggled_quality_for_%0_entries=Vérification_de_qualité_modifiée_pour_%0_entrées -Toggled_print_status_for_%0_entries=Statut_d'impression_modifié_pour_%0_entrées -Toggled_relevance_for_%0_entries=Pertinence_modifiée_pour_%0_entrées Marked_all_%0_selected_entries=%0_entrées_sélectionnées_étiquetées Marked_selected_entry=Entrées_sélectionnées_étiquetées @@ -1632,3 +1629,7 @@ Get_fulltext=Obtenir_le_document Download_from_URL=Télécharger_depuis_l'URL Decryption_not_supported.=Déchiffrement_non_supporté. + +Cleared_'%0'_for_%1_entries=Réinitialisés_'%0'_pour_%1_entrées +Set_'%0'_to_'%1'_for_%2_entries='%0'_mis_à_'%1'_pour_%2_entrées +Toggled_'%0'_for_%1_entries='%0'_modifiée_pour_%1_entrées \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index dd570bfda3e3..9c6b815b6e89 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1225,9 +1225,6 @@ Show_gridlines=Tampilkan_garis_kisi Show_printed_status=Tampilkan_status_pencetakan Show_read_status=Tampilkan_status_pembacaan Table_row_height_padding=Lapisan_tinggi_baris_tabel -Toggled_quality_for_%0_entries= -Toggled_print_status_for_%0_entries= -Toggled_relevance_for_%0_entries= Marked_all_%0_selected_entries=Semua_%0_entri_pilihan_ditandai Marked_selected_entry=Entri_pilihan_ditandai @@ -1607,3 +1604,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 4a968c509d17..39a340b50f7f 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1325,9 +1325,6 @@ Show_gridlines=Mostra_la_griglia Show_printed_status=Mostra_lo_stato_di_stampa Show_read_status=Mostra_lo_stato_di_lettura Table_row_height_padding=Altezza_delle_righe -Toggled_quality_for_%0_entries=Modificata_la_valutazione_di_qualit\u00e0_per_'%0'_voce/i -Toggled_print_status_for_%0_entries=Invertito_lo_stato_di_stampa_per_'%0'_voce/i -Toggled_relevance_for_%0_entries=Modificata_la_valutazione_di_rilevanza_per_'%0'_voce/i Marked_all_%0_selected_entries=Contrassegnate_tutte_le_'%0'_voci_selezionate Marked_selected_entry=Contrassegnate_le_voci_selezionate @@ -1707,3 +1704,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries=Reinizializzati_'%0'_per_%1_voce/i +Set_'%0'_to_'%1'_for_%2_entries='%0'_impostata_a_'%1'_per_%2_voce/i +Toggled_'%0'_for_%1_entries=Modificata_la_valutazione_di_'%0'_per_%1_voce/i diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 57f75f7881af..ca4dd9cd0c1a 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1996,9 +1996,6 @@ Show_gridlines=グリッド線を表示 Show_printed_status=印刷済情報を表示 Show_read_status=既読情報を表示 Table_row_height_padding=表の行高パディング -Toggled_quality_for_%0_entries=%0個の項目の品質を変更しました -Toggled_print_status_for_%0_entries=%0個の項目の印刷済情報を変更しました -Toggled_relevance_for_%0_entries=%0個の項目の関連性を変更しました Marked_all_%0_selected_entries=%0個の選択項目全てに標識を付けました Marked_selected_entry=選択した項目に標識を付けました @@ -2352,3 +2349,7 @@ Get_fulltext=フルテキストを得る Download_from_URL=URLからダウンロード Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 1f60cf878dc4..afed41b4612c 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1998,9 +1998,6 @@ Show_gridlines= Show_printed_status= Show_read_status= Table_row_height_padding= -Toggled_quality_for_%0_entries= -Toggled_print_status_for_%0_entries= -Toggled_relevance_for_%0_entries= Marked_all_%0_selected_entries= Marked_selected_entry= @@ -2383,3 +2380,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index c71a623efe3a..6e7b9114f715 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2393,9 +2393,6 @@ Show_gridlines= Show_printed_status= Show_read_status= Table_row_height_padding= -Toggled_quality_for_%0_entries= -Toggled_print_status_for_%0_entries= -Toggled_relevance_for_%0_entries= Marked_all_%0_selected_entries= Marked_selected_entry= @@ -2779,3 +2776,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 39cf57b780c4..1190bb82af99 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1222,9 +1222,6 @@ Show_gridlines=Mostrar_linhas_de_grade Show_printed_status=Mostrar_status_de_impressão Show_read_status=Mostrar_status_da_leitura Table_row_height_padding=Preenchimento_(padding)_da_altura_das_linhas_da_tabela -Toggled_quality_for_%0_entries=Qualidade_de_%0_registros_foi_alternada -Toggled_print_status_for_%0_entries=%0_registros_tiveram_seus_status_de_impressão_de_alternados -Toggled_relevance_for_%0_entries=%0_registros_tiveram_sua_relevância_alternada Marked_all_%0_selected_entries=Marcadas_todos_os_%0_registros Marked_selected_entry=Registro_selecionado_marcado @@ -1601,3 +1598,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries=Definir_'%0'_'%1'_para_%2_registros +Toggled_'%0'_for_%1_entries= \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 153a9f546306..c41e1d5b115f 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1969,9 +1969,6 @@ Show_gridlines=Показать_сетку Show_printed_status=Показать_статус_'печать' Show_read_status=Показать_статус_'чтение' Table_row_height_padding=Отступ_по_высоте_для_строки_таблицы -Toggled_quality_for_%0_entries=Изменение_качества_для_%0_записей -Toggled_print_status_for_%0_entries=Статус_'печать'_изменен_для_%0_записей -Toggled_relevance_for_%0_entries=Изменение_соответствия_для_%0_записей Marked_selected_entry=Отмечены_выбранные_записи Marked_all_%0_selected_entries=Отмечены_все_%0_выбранные_записи @@ -2351,3 +2348,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries=Установить_'%0'_'%1'_для_%2_записей +Toggled_'%0'_for_%1_entries=Изменение_'%0'_для_%1_записей \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 2d3704560211..05116b28f173 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1204,9 +1204,6 @@ Toggle_entry_preview=Växla_postvisning Toggle_groups_interface=Växla_grupphantering Toggle_print_status=Växla_utskriftsstatus Toggle_relevance=Växla_relevans -Toggled_print_status_for_%0_entries=Växlade_utskriftsstatus_för_%0_poster -Toggled_quality_for_%0_entries=Växlade_kvalitet_för_%0_poster -Toggled_relevance_for_%0_entries=Växlade_relevans_för_%0_poster Toggle_quality_assured=Växla_kvalitetssäkring Treatment_of_first_names=Hantering_av_förnamn Try_different_encoding=Prova_en_annan_teckenkodning @@ -1546,3 +1543,7 @@ Download_from_URL=Ladda_ned_från_URL Decryption_not_supported.=Avkryptering_stöds_ej. + +Cleared_'%0'_for_%1_entries=Rensade_'%0'_för_%1_poster +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries=Växlade_'%0'_för_%1_poster diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 157821211811..d03ebadce7b4 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1242,9 +1242,6 @@ Show_gridlines=Izgarayı_göster Show_printed_status=Yazdırma_statüsünü_göster Show_read_status=Okunma_statüsünü_göster Table_row_height_padding=Tablo_satır_yüksekliği_dolgusu -Toggled_quality_for_%0_entries=%0_girdiler_için_kalite_değiştirildi -Toggled_print_status_for_%0_entries=%0_girdiler_için_yazdırma_statüsü_değiştirildi -Toggled_relevance_for_%0_entries=%0_girdiler_için_uygunluk_değiştirildi Marked_all_%0_selected_entries=Tüm_%0_seçilmiş_girdi_işaretlendi Marked_selected_entry=Seçilmiş_girdi_işaretlendi @@ -1620,3 +1617,7 @@ Get_fulltext=Tammetni_getir Download_from_URL=URL'den_indir Decryption_not_supported.=Şifre_çözme_desteklenmiyor. + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries=%2_girdiler_için_'%0'_'%1'a_ata +Toggled_'%0'_for_%1_entries=%1_girdiler_için_'%0'_değiştirildi \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 1dad633d9909..611ea4edf3d4 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1992,9 +1992,6 @@ Show_gridlines= Show_printed_status= Show_read_status= Table_row_height_padding= -Toggled_quality_for_%0_entries= -Toggled_print_status_for_%0_entries= -Toggled_relevance_for_%0_entries= Marked_all_%0_selected_entries= Marked_selected_entry= @@ -2375,3 +2372,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 30c6ac86d07a..0f3d9a92357f 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1299,9 +1299,6 @@ Show_gridlines=显示边框 Show_printed_status=显示打印状态 Show_read_status=显示已读状态 Table_row_height_padding=表格行高 -Toggled_quality_for_%0_entries= -Toggled_print_status_for_%0_entries= -Toggled_relevance_for_%0_entries= Marked_all_%0_selected_entries=标记共_%0_条选中的记录 Marked_selected_entry=标记选中的记录 @@ -1614,3 +1611,7 @@ Get_fulltext= Download_from_URL= Decryption_not_supported.= + +Cleared_'%0'_for_%1_entries= +Set_'%0'_to_'%1'_for_%2_entries= +Toggled_'%0'_for_%1_entries= \ No newline at end of file From 3aca346cf02736a74b75ea6636c3e9228c5d11cc Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 15 Apr 2016 17:50:20 +0200 Subject: [PATCH 116/268] First attempt --- .../net/sf/jabref/benchmarks/Benchmarks.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index 3cdbf46d929e..0194ac6586dc 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -18,7 +18,10 @@ import net.sf.jabref.exporter.SavePreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.layout.format.HTMLChars; +import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; import net.sf.jabref.logic.search.SearchQuery; +import net.sf.jabref.logic.util.strings.HTMLUnicodeConversionMaps; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.database.BibDatabaseModeDetection; @@ -36,6 +39,7 @@ public class Benchmarks { String bibtexString; BibDatabase database = new BibDatabase(); + List conversionStrings = new ArrayList<>(); @Setup public void init() throws IOException, SaveException { @@ -60,6 +64,16 @@ public void init() throws IOException, SaveException { new SavePreferences()); bibtexString = stringWriter.toString(); + List latexSymbols = new ArrayList<>(HTMLUnicodeConversionMaps.UNICODE_LATEX_CONVERSION_MAP.values()); + int symbolcount = latexSymbols.size(); + StringBuilder sb = new StringBuilder(); + sb.append("{A} \\textbf{bold} "); + sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(" {\\it italic} {"); + sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append("} abc"); + conversionStrings.add(sb.toString()); } @Benchmark @@ -94,6 +108,26 @@ public BibDatabaseMode inferBibDatabaseMode() { return BibDatabaseModeDetection.inferMode(database); } + @Benchmark + public List latexToUnicodeConversion() { + List result = new ArrayList<>(1000); + LatexToUnicodeFormatter f = new LatexToUnicodeFormatter(); + for (String s : conversionStrings) { + result.add(f.format(s)); + } + return result; + } + + @Benchmark + public List latexToHTMLConversion() { + List result = new ArrayList<>(1000); + HTMLChars f = new HTMLChars(); + for (String s : conversionStrings) { + result.add(f.format(s)); + } + return result; + } + public static void main(String[] args) throws IOException, RunnerException { Main.main(args); } From af16d0b7b20c9a4883940aaf05ffa14ddadd5cda Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 15 Apr 2016 18:57:42 +0200 Subject: [PATCH 117/268] Updated benchmarks --- .../net/sf/jabref/benchmarks/Benchmarks.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index 0194ac6586dc..c1f5c6b911d7 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -18,6 +18,7 @@ import net.sf.jabref.exporter.SavePreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.layout.format.HTMLChars; import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; import net.sf.jabref.logic.search.SearchQuery; @@ -39,7 +40,8 @@ public class Benchmarks { String bibtexString; BibDatabase database = new BibDatabase(); - List conversionStrings = new ArrayList<>(); + List latexConversionStrings = new ArrayList<>(); + List htmlConversionStrings = new ArrayList<>(); @Setup public void init() throws IOException, SaveException { @@ -73,7 +75,18 @@ public void init() throws IOException, SaveException { sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); sb.append("} abc"); - conversionStrings.add(sb.toString()); + latexConversionStrings.add(sb.toString()); + + List htmlSymbols = new ArrayList<>(HTMLUnicodeConversionMaps.HTML_LATEX_CONVERSION_MAP.keySet()); + symbolcount = htmlSymbols.size(); + sb = new StringBuilder(); + sb.append("A bold "); + sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(" italic "); + sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append("– abc"); + htmlConversionStrings.add(sb.toString()); } @Benchmark @@ -112,7 +125,7 @@ public BibDatabaseMode inferBibDatabaseMode() { public List latexToUnicodeConversion() { List result = new ArrayList<>(1000); LatexToUnicodeFormatter f = new LatexToUnicodeFormatter(); - for (String s : conversionStrings) { + for (String s : latexConversionStrings) { result.add(f.format(s)); } return result; @@ -122,7 +135,17 @@ public List latexToUnicodeConversion() { public List latexToHTMLConversion() { List result = new ArrayList<>(1000); HTMLChars f = new HTMLChars(); - for (String s : conversionStrings) { + for (String s : latexConversionStrings) { + result.add(f.format(s)); + } + return result; + } + + @Benchmark + public List htmlToLatexConversion() { + List result = new ArrayList<>(1000); + HtmlToLatexFormatter f = new HtmlToLatexFormatter(); + for (String s : htmlConversionStrings) { result.add(f.format(s)); } return result; From 973a39d9fa61ad9149db778e27112ecaeb13d712 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 14 Apr 2016 23:21:16 +0200 Subject: [PATCH 118/268] Replaced regular expressions with plain strings in HTML/Unicode conversion map and fixed #405 --- CHANGELOG.md | 1 + .../net/sf/jabref/benchmarks/Benchmarks.java | 20 +- .../bibtexfields/HtmlToLatexFormatter.java | 16 +- .../bibtexfields/UnicodeToLatexFormatter.java | 2 +- .../strings/HTMLUnicodeConversionMaps.java | 796 +++++++++--------- 5 files changed, 418 insertions(+), 417 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b75d8828dc9b..4b5ee6600ff6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1457](https://github.com/JabRef/jabref/issues/1457): Support multiple words inside LaTeX commands to RTF export - Entries retain their groupmembership when undoing their cut/deletion - Fixed [#1450](https://github.com/JabRef/jabref/issues/1450): EntryEditor is restored in the correct size after preference changes +- Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index c1f5c6b911d7..6a391a6fa904 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -38,10 +38,10 @@ @State(Scope.Thread) public class Benchmarks { - String bibtexString; - BibDatabase database = new BibDatabase(); - List latexConversionStrings = new ArrayList<>(); - List htmlConversionStrings = new ArrayList<>(); + private String bibtexString; + private final BibDatabase database = new BibDatabase(); + private final List latexConversionStrings = new ArrayList<>(); + private final List htmlConversionStrings = new ArrayList<>(); @Setup public void init() throws IOException, SaveException { @@ -70,10 +70,10 @@ public void init() throws IOException, SaveException { int symbolcount = latexSymbols.size(); StringBuilder sb = new StringBuilder(); sb.append("{A} \\textbf{bold} "); - sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(latexSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); sb.append(" {\\it italic} {"); - sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); - sb.append(latexSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(latexSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); + sb.append(latexSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); sb.append("} abc"); latexConversionStrings.add(sb.toString()); @@ -81,10 +81,10 @@ public void init() throws IOException, SaveException { symbolcount = htmlSymbols.size(); sb = new StringBuilder(); sb.append("A bold "); - sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); sb.append(" italic "); - sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); - sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt()) % symbolcount)); + sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); + sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); sb.append("– abc"); htmlConversionStrings.add(sb.toString()); } diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java index 3df77f07a2bb..6f0a2d791801 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java @@ -81,7 +81,7 @@ public String format(String text) { // Handle text based HTML entities Set patterns = HTMLUnicodeConversionMaps.HTML_LATEX_CONVERSION_MAP.keySet(); for (String pattern : patterns) { - result = result.replaceAll(pattern, HTMLUnicodeConversionMaps.HTML_LATEX_CONVERSION_MAP.get(pattern)); + result = result.replace(pattern, HTMLUnicodeConversionMaps.HTML_LATEX_CONVERSION_MAP.get(pattern)); } // Handle numerical HTML entities @@ -89,7 +89,7 @@ public String format(String text) { while (m.find()) { int num = Integer.decode(m.group(1).replace("x", "#") + m.group(3)); if (HTMLUnicodeConversionMaps.NUMERICAL_LATEX_CONVERSION_MAP.containsKey(num)) { - result = result.replaceAll("&#" + m.group(1) + m.group(2) + m.group(3) + ";", + result = result.replace("&#" + m.group(1) + m.group(2) + m.group(3) + ";", HTMLUnicodeConversionMaps.NUMERICAL_LATEX_CONVERSION_MAP.get(num)); } } @@ -100,14 +100,14 @@ public String format(String text) { int num = Integer.decode(m.group(2).replace("x", "#") + m.group(4)); if (HTMLUnicodeConversionMaps.ESCAPED_ACCENTS.containsKey(num)) { if ("i".equals(m.group(1))) { - result = result.replaceAll(m.group(1) + "&#" + m.group(2) + m.group(3) + m.group(4) + ";", - "\\{\\\\" + HTMLUnicodeConversionMaps.ESCAPED_ACCENTS.get(num) + "\\{\\\\i\\}\\}"); + result = result.replace(m.group(1) + "&#" + m.group(2) + m.group(3) + m.group(4) + ";", + "{\\" + HTMLUnicodeConversionMaps.ESCAPED_ACCENTS.get(num) + "{\\i}}"); } else if ("j".equals(m.group(1))) { - result = result.replaceAll(m.group(1) + "&#" + m.group(2) + m.group(3) + m.group(4) + ";", - "\\{\\\\" + HTMLUnicodeConversionMaps.ESCAPED_ACCENTS.get(num) + "\\{\\\\j\\}\\}"); + result = result.replace(m.group(1) + "&#" + m.group(2) + m.group(3) + m.group(4) + ";", + "{\\" + HTMLUnicodeConversionMaps.ESCAPED_ACCENTS.get(num) + "{\\j}}"); } else { - result = result.replaceAll(m.group(1) + "&#" + m.group(2) + m.group(3) + m.group(4) + ";", "\\{\\\\" - + HTMLUnicodeConversionMaps.ESCAPED_ACCENTS.get(num) + "\\{" + m.group(1) + "\\}\\}"); + result = result.replace(m.group(1) + "&#" + m.group(2) + m.group(3) + m.group(4) + ";", + "{\\" + HTMLUnicodeConversionMaps.ESCAPED_ACCENTS.get(num) + "{" + m.group(1) + "}}"); } } } diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java index fd347b39b36a..7c366134364d 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java @@ -41,7 +41,7 @@ public String format(String text) { // Standard symbols Set chars = HTMLUnicodeConversionMaps.UNICODE_LATEX_CONVERSION_MAP.keySet(); for (Character character : chars) { - result = result.replaceAll(character.toString(), + result = result.replace(character.toString(), HTMLUnicodeConversionMaps.UNICODE_LATEX_CONVERSION_MAP.get(character)); } diff --git a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java index 84de81f273b0..56165bb7bad8 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java @@ -20,470 +20,470 @@ public class HTMLUnicodeConversionMaps { // An array of arrays of strings in the format: // {"decimal number of HTML entity", "text HTML entity", "corresponding LaTeX command"} // Leaving a field empty is OK as it then will not be included - private static final String[][] CONVERSION_LIST = new String[][] {{"160", "nbsp", "\\{~\\}"}, // no-break space = non-breaking space, + private static final String[][] CONVERSION_LIST = new String[][] {{"160", "nbsp", "{~}"}, // no-break space = non-breaking space, // U+00A0 ISOnum - {"161", "iexcl", "\\{\\\\textexclamdown\\}"}, // inverted exclamation mark, U+00A1 ISOnum - {"162", "cent", "\\{\\\\textcent\\}"}, // cent sign, U+00A2 ISOnum - {"163", "pound", "\\{\\\\pounds\\}"}, // pound sign, U+00A3 ISOnum - {"164", "curren", "\\{\\\\textcurrency\\}"}, // currency sign, U+00A4 ISOnum - {"165", "yen", "\\{\\\\textyen\\}"}, // yen sign = yuan sign, U+00A5 ISOnum - {"166", "brvbar", "\\{\\\\textbrokenbar\\}"}, // broken bar = broken vertical bar, + {"161", "iexcl", "{\\textexclamdown}"}, // inverted exclamation mark, U+00A1 ISOnum + {"162", "cent", "{\\textcent}"}, // cent sign, U+00A2 ISOnum + {"163", "pound", "{\\pounds}"}, // pound sign, U+00A3 ISOnum + {"164", "curren", "{\\textcurrency}"}, // currency sign, U+00A4 ISOnum + {"165", "yen", "{\\textyen}"}, // yen sign = yuan sign, U+00A5 ISOnum + {"166", "brvbar", "{\\textbrokenbar}"}, // broken bar = broken vertical bar, // U+00A6 ISOnum - {"167", "sect", "\\{\\\\S\\}"}, // section sign, U+00A7 ISOnum - {"168", "uml", "\\{\\\\\"\\{\\}\\}"}, // diaeresis = spacing diaeresis, + {"167", "sect", "{{\\S}}"}, // section sign, U+00A7 ISOnum + {"168", "uml", "{\\\"{}}"}, // diaeresis = spacing diaeresis, // U+00A8 ISOdia - {"169", "copy", "\\{\\\\copyright\\}"}, // copyright sign, U+00A9 ISOnum - {"170", "ordf", "\\{\\\\textordfeminine\\}"}, // feminine ordinal indicator, U+00AA ISOnum - {"171", "laquo", "\\{\\\\guillemotleft\\}"}, // left-pointing double angle quotation mark + {"169", "copy", "{\\copyright}"}, // copyright sign, U+00A9 ISOnum + {"170", "ordf", "{\\textordfeminine}"}, // feminine ordinal indicator, U+00AA ISOnum + {"171", "laquo", "{\\guillemotleft}"}, // left-pointing double angle quotation mark // = left pointing guillemet, U+00AB ISOnum - {"172", "not", "\\$\\\\neg\\$"}, // not sign, U+00AC ISOnum - {"173", "shy", "\\\\-"}, // soft hyphen = discretionary hyphen, + {"172", "not", "$\\neg$"}, // not sign, U+00AC ISOnum + {"173", "shy", "\\-"}, // soft hyphen = discretionary hyphen, // U+00AD ISOnum - {"174", "reg", "\\{\\\\textregistered\\}"}, // registered sign = registered trade mark sign, + {"174", "reg", "{\\textregistered}"}, // registered sign = registered trade mark sign, // U+00AE ISOnum - {"175", "macr", "\\{\\\\=\\{\\}\\}"}, // macron = spacing macron = overline + {"175", "macr", "{\\={}}"}, // macron = spacing macron = overline // = APL overbar, U+00AF ISOdia - {"176", "deg", "\\$\\\\deg\\$"}, // degree sign, U+00B0 ISOnum - {"177", "plusmn", "\\$\\\\pm\\$"}, // plus-minus sign = plus-or-minus sign, + {"176", "deg", "$\\deg$"}, // degree sign, U+00B0 ISOnum + {"177", "plusmn", "$\\pm$"}, // plus-minus sign = plus-or-minus sign, // U+00B1 ISOnum - {"178", "sup2", "\\\\textsuperscript\\{2\\}"}, // superscript two = superscript digit two + {"178", "sup2", "\\textsuperscript{2}"}, // superscript two = superscript digit two // = squared, U+00B2 ISOnum - {"179", "sup3", "\\\\textsuperscript\\{3\\}"}, // superscript three = superscript digit three + {"179", "sup3", "\\textsuperscript{3}"}, // superscript three = superscript digit three // = cubed, U+00B3 ISOnum - {"180", "acute", "\\{\\\\'\\{\\}\\}"}, // acute accent = spacing acute, + {"180", "acute", "{\\'{}}"}, // acute accent = spacing acute, // U+00B4 ISOdia - {"181", "micro", "\\$\\\\mu\\$"}, // micro sign, U+00B5 ISOnum - {"", "mu", "\\$\\\\mu\\$"}, // micro sign, U+00B5 ISOnum - {"182", "para", "\\{\\\\P\\}"}, // pilcrow sign = paragraph sign, + {"181", "micro", "$\\mu$"}, // micro sign, U+00B5 ISOnum + {"", "mu", "$\\mu$"}, // micro sign, U+00B5 ISOnum + {"182", "para", "{{\\P}}"}, // pilcrow sign = paragraph sign, // U+00B6 ISOnum - {"183", "middot", "\\$\\\\cdot\\$"}, // middle dot = Georgian comma + {"183", "middot", "$\\cdot$"}, // middle dot = Georgian comma // = Greek middle dot, U+00B7 ISOnum - {"184", "cedil", "\\{\\\\c\\{\\}\\}"}, // cedilla = spacing cedilla, U+00B8 ISOdia - {"185", "sup1", "\\\\textsuperscript\\{1\\}"}, // superscript one = superscript digit one, + {"184", "cedil", "{\\c{}}"}, // cedilla = spacing cedilla, U+00B8 ISOdia + {"185", "sup1", "\\textsuperscript{1}"}, // superscript one = superscript digit one, // U+00B9 ISOnum - {"186", "ordm", "\\{\\\\textordmasculine\\}"}, // masculine ordinal indicator, + {"186", "ordm", "{\\textordmasculine}"}, // masculine ordinal indicator, // U+00BA ISOnum - {"187", "raquo", "\\{\\\\guillemotright\\}"}, // right-pointing double angle quotation mark + {"187", "raquo", "{\\guillemotright}"}, // right-pointing double angle quotation mark // = right pointing guillemet, U+00BB ISOnum - {"188", "frac14", "\\$\\\\sfrac\\{1\\}\\{4\\}\\$"}, // vulgar fraction one quarter + {"188", "frac14", "$\\sfrac{1}{4}$"}, // vulgar fraction one quarter // = fraction one quarter, U+00BC ISOnum - {"189", "frac12", "\\$\\\\sfrac\\{1\\}\\{2\\}\\$"}, // vulgar fraction one half + {"189", "frac12", "$\\sfrac{1}{2}$"}, // vulgar fraction one half // = fraction one half, U+00BD ISOnum - {"190", "frac34", "\\$\\\\sfrac\\{3\\}\\{4\\}\\$"}, // vulgar fraction three quarters + {"190", "frac34", "$\\sfrac{3}{4}$"}, // vulgar fraction three quarters // = fraction three quarters, U+00BE ISOnum - {"191", "iquest", "\\{\\\\textquestiondown\\}"}, // inverted question mark + {"191", "iquest", "{\\textquestiondown}"}, // inverted question mark // = turned question mark, U+00BF ISOnum - {"192", "Agrave", "\\{\\\\`\\{A\\}\\}"}, // latin capital letter A with grave + {"192", "Agrave", "{{\\`{A}}}"}, // latin capital letter A with grave // = latin capital letter A grave, // U+00C0 ISOlat1 - {"193", "Aacute", "\\{\\\\'\\{A\\}\\}"}, // latin capital letter A with acute, + {"193", "Aacute", "{{\\'{A}}}"}, // latin capital letter A with acute, // U+00C1 ISOlat1 - {"194", "Acirc", "\\{\\\\\\^\\{A\\}\\}"}, // latin capital letter A with circumflex, + {"194", "Acirc", "{{\\^{A}}}"}, // latin capital letter A with circumflex, // U+00C2 ISOlat1 - {"195", "Atilde", "\\{\\\\~\\{A\\}\\}"}, // latin capital letter A with tilde, + {"195", "Atilde", "{{\\~{A}}}"}, // latin capital letter A with tilde, // U+00C3 ISOlat1 - {"196", "Auml", "\\{\\\\\"\\{A\\}\\}"}, // latin capital letter A with diaeresis, + {"196", "Auml", "{{\\\"{A}}}"}, // latin capital letter A with diaeresis, // U+00C4 ISOlat1 - {"197", "Aring", "\\{\\{\\\\AA\\}\\}"}, // latin capital letter A with ring above + {"197", "Aring", "{{\\AA}}"}, // latin capital letter A with ring above // = latin capital letter A ring, // U+00C5 ISOlat1 - {"198", "AElig", "\\{\\\\AE\\}"}, // latin capital letter AE + {"198", "AElig", "{{\\AE}}"}, // latin capital letter AE // = latin capital ligature AE, // U+00C6 ISOlat1 - {"199", "Ccedil", "\\{\\\\c\\{C\\}\\}"}, // latin capital letter C with cedilla, + {"199", "Ccedil", "{{\\c{C}}}"}, // latin capital letter C with cedilla, // U+00C7 ISOlat1 - {"200", "Egrave", "\\{\\\\`\\{E\\}\\}"}, // latin capital letter E with grave, + {"200", "Egrave", "{{\\`{E}}}"}, // latin capital letter E with grave, // U+00C8 ISOlat1 - {"201", "Eacute", "\\{\\\\'\\{E\\}\\}"}, // latin capital letter E with acute, + {"201", "Eacute", "{{\\'{E}}}"}, // latin capital letter E with acute, // U+00C9 ISOlat1 - {"202", "Ecirc", "\\{\\\\\\^\\{E\\}\\}"}, // latin capital letter E with circumflex, + {"202", "Ecirc", "{{\\^{E}}}"}, // latin capital letter E with circumflex, // U+00CA ISOlat1 - {"203", "Euml", "\\{\\\\\"\\{E\\}\\}"}, // latin capital letter E with diaeresis, + {"203", "Euml", "{{\\\"{E}}}"}, // latin capital letter E with diaeresis, // U+00CB ISOlat1 - {"204", "Igrave", "\\{\\\\`\\{I\\}\\}"}, // latin capital letter I with grave, + {"204", "Igrave", "{{\\`{I}}}"}, // latin capital letter I with grave, // U+00CC ISOlat1 - {"205", "Iacute", "\\{\\\\'\\{I\\}\\}"}, // latin capital letter I with acute, + {"205", "Iacute", "{{\\'{I}}}"}, // latin capital letter I with acute, // U+00CD ISOlat1 - {"206", "Icirc", "\\{\\\\\\^\\{I\\}\\}"}, // latin capital letter I with circumflex, + {"206", "Icirc", "{{\\^{I}}}"}, // latin capital letter I with circumflex, // U+00CE ISOlat1 - {"207", "Iuml", "\\{\\\\\"\\{I\\}\\}"}, // latin capital letter I with diaeresis, + {"207", "Iuml", "{{\\\"{I}}}"}, // latin capital letter I with diaeresis, // U+00CF ISOlat1 - {"208", "ETH", "\\{\\\\DH\\}"}, // latin capital letter ETH, U+00D0 ISOlat1 - {"209", "Ntilde", "\\{\\\\~\\{N\\}\\}"}, // latin capital letter N with tilde, + {"208", "ETH", "{{\\DH}}"}, // latin capital letter ETH, U+00D0 ISOlat1 + {"209", "Ntilde", "{{\\~{N}}}"}, // latin capital letter N with tilde, // U+00D1 ISOlat1 - {"210", "Ograve", "\\{\\\\`\\{O\\}\\}"}, // latin capital letter O with grave, + {"210", "Ograve", "{{\\`{O}}}"}, // latin capital letter O with grave, // U+00D2 ISOlat1 - {"211", "Oacute", "\\{\\\\'\\{O\\}\\}"}, // latin capital letter O with acute, + {"211", "Oacute", "{{\\'{O}}}"}, // latin capital letter O with acute, // U+00D3 ISOlat1 - {"212", "Ocirc", "\\{\\\\\\^\\{O\\}\\}"}, // latin capital letter O with circumflex, + {"212", "Ocirc", "{{\\^{O}}}"}, // latin capital letter O with circumflex, // U+00D4 ISOlat1 - {"213", "Otilde", "\\{\\\\~\\{O\\}\\}"}, // latin capital letter O with tilde, + {"213", "Otilde", "{{\\~{O}}}"}, // latin capital letter O with tilde, // U+00D5 ISOlat1 - {"214", "Ouml", "\\{\\\\\"\\{O\\}\\}"}, // latin capital letter O with diaeresis, + {"214", "Ouml", "{{\\\"{O}}}"}, // latin capital letter O with diaeresis, // U+00D6 ISOlat1 - {"215", "times", "\\$\\\\times\\$"}, // multiplication sign, U+00D7 ISOnum - {"216", "Oslash", "\\{\\\\O\\}"}, // latin capital letter O with stroke + {"215", "times", "$\\times$"}, // multiplication sign, U+00D7 ISOnum + {"216", "Oslash", "{{\\O}}"}, // latin capital letter O with stroke // = latin capital letter O slash, // U+00D8 ISOlat1 - {"217", "Ugrave", "\\{\\\\`\\{U\\}\\}"}, // latin capital letter U with grave, + {"217", "Ugrave", "{{\\`{U}}}"}, // latin capital letter U with grave, // U+00D9 ISOlat1 - {"218", "Uacute", "\\{\\\\'\\{U\\}\\}"}, // latin capital letter U with acute, + {"218", "Uacute", "{{\\'{U}}}"}, // latin capital letter U with acute, // U+00DA ISOlat1 - {"219", "Ucirc", "\\{\\\\\\^\\{U\\}\\}"}, // latin capital letter U with circumflex, + {"219", "Ucirc", "{{\\^{U}}}"}, // latin capital letter U with circumflex, // U+00DB ISOlat1 - {"220", "Uuml", "\\{\\\\\"\\{U\\}\\}"}, // latin capital letter U with diaeresis, + {"220", "Uuml", "{{\\\"{U}}}"}, // latin capital letter U with diaeresis, // U+00DC ISOlat1 - {"221", "Yacute", "\\{\\\\'\\{Y\\}\\}"}, // latin capital letter Y with acute, + {"221", "Yacute", "{{\\'{Y}}}"}, // latin capital letter Y with acute, // U+00DD ISOlat1 - {"222", "THORN", "\\{\\\\TH\\}"}, // latin capital letter THORN, + {"222", "THORN", "{{\\TH}}"}, // latin capital letter THORN, // U+00DE ISOlat1 - {"223", "szlig", "\\{\\\\ss\\}"}, // latin small letter sharp s = ess-zed, + {"223", "szlig", "{\\ss}"}, // latin small letter sharp s = ess-zed, // U+00DF ISOlat1 - {"224", "agrave", "\\{\\\\`\\{a\\}\\}"}, // latin small letter a with grave + {"224", "agrave", "{\\`{a}}"}, // latin small letter a with grave // = latin small letter a grave, // U+00E0 ISOlat1 - {"225", "aacute", "\\{\\\\'\\{a\\}\\}"}, // latin small letter a with acute, + {"225", "aacute", "{\\'{a}}"}, // latin small letter a with acute, // U+00E1 ISOlat1 - {"226", "acirc", "\\{\\\\\\^\\{a\\}\\}"}, // latin small letter a with circumflex, + {"226", "acirc", "{\\^{a}}"}, // latin small letter a with circumflex, // U+00E2 ISOlat1 - {"227", "atilde", "\\{\\\\~\\{a\\}\\}"}, // latin small letter a with tilde, + {"227", "atilde", "{\\~{a}}"}, // latin small letter a with tilde, // U+00E3 ISOlat1 - {"228", "auml", "\\{\\\\\"\\{a\\}\\}"}, // latin small letter a with diaeresis, + {"228", "auml", "{\\\"{a}}"}, // latin small letter a with diaeresis, // U+00E4 ISOlat1 - {"229", "aring", "\\{\\{\\\\aa\\}\\}"}, // latin small letter a with ring above + {"229", "aring", "{{\\aa}}"}, // latin small letter a with ring above // = latin small letter a ring, // U+00E5 ISOlat1 - {"230", "aelig", "\\{\\\\ae\\}"}, // latin small letter ae + {"230", "aelig", "{\\ae}"}, // latin small letter ae // = latin small ligature ae, U+00E6 ISOlat1 - {"231", "ccedil", "\\{\\\\c\\{c\\}\\}"}, // latin small letter c with cedilla, + {"231", "ccedil", "{\\c{c}}"}, // latin small letter c with cedilla, // U+00E7 ISOlat1 - {"232", "egrave", "\\{\\\\`\\{e\\}\\}"}, // latin small letter e with grave, + {"232", "egrave", "{\\`{e}}"}, // latin small letter e with grave, // U+00E8 ISOlat1 - {"233", "eacute", "\\{\\\\'\\{e\\}\\}"}, // latin small letter e with acute, + {"233", "eacute", "{\\'{e}}"}, // latin small letter e with acute, // U+00E9 ISOlat1 - {"234", "ecirc", "\\{\\\\\\^\\{e\\}\\}"}, // latin small letter e with circumflex, + {"234", "ecirc", "{\\^{e}}"}, // latin small letter e with circumflex, // U+00EA ISOlat1 - {"235", "euml", "\\{\\\\\"\\{e\\}\\}"}, // latin small letter e with diaeresis, + {"235", "euml", "{\\\"{e}}"}, // latin small letter e with diaeresis, // U+00EB ISOlat1 - {"236", "igrave", "\\{\\\\`\\{i\\}\\}"}, // latin small letter i with grave, + {"236", "igrave", "{\\`{i}}"}, // latin small letter i with grave, // U+00EC ISOlat1 - {"237", "iacute", "\\{\\\\'\\{i\\}\\}"}, // latin small letter i with acute, + {"237", "iacute", "{\\'{i}}"}, // latin small letter i with acute, // U+00ED ISOlat1 - {"238", "icirc", "\\{\\\\\\^\\{i\\}\\}"}, // latin small letter i with circumflex, + {"238", "icirc", "{\\^{i}}"}, // latin small letter i with circumflex, // U+00EE ISOlat1 - {"239", "iuml", "\\{\\\\\"\\{i\\}\\}"}, // latin small letter i with diaeresis, + {"239", "iuml", "{\\\"{i}}"}, // latin small letter i with diaeresis, // U+00EF ISOlat1 - {"240", "eth", "\\{\\\\dh\\}"}, // latin small letter eth, U+00F0 ISOlat1 - {"241", "ntilde", "\\{\\\\~\\{n\\}\\}"}, // latin small letter n with tilde, + {"240", "eth", "{\\dh}"}, // latin small letter eth, U+00F0 ISOlat1 + {"241", "ntilde", "{\\~{n}}"}, // latin small letter n with tilde, // U+00F1 ISOlat1 - {"242", "ograve", "\\{\\\\`\\{o\\}\\}"}, // latin small letter o with grave, + {"242", "ograve", "{\\`{o}}"}, // latin small letter o with grave, // U+00F2 ISOlat1 - {"243", "oacute", "\\{\\\\'\\{o\\}\\}"}, // latin small letter o with acute, + {"243", "oacute", "{\\'{o}}"}, // latin small letter o with acute, // U+00F3 ISOlat1 - {"244", "ocirc", "\\{\\\\\\^\\{o\\}\\}"}, // latin small letter o with circumflex, + {"244", "ocirc", "{\\^{o}}"}, // latin small letter o with circumflex, // U+00F4 ISOlat1 - {"245", "otilde", "\\{\\\\~\\{o\\}\\}"}, // latin small letter o with tilde, + {"245", "otilde", "{\\~{o}}"}, // latin small letter o with tilde, // U+00F5 ISOlat1 - {"246", "ouml", "\\{\\\\\"\\{o\\}\\}"}, // latin small letter o with diaeresis, + {"246", "ouml", "{\\\"{o}}"}, // latin small letter o with diaeresis, // U+00F6 ISOlat1 - {"247", "divide", "\\$\\\\div\\$"}, // division sign, U+00F7 ISOnum - {"248", "oslash", "\\{\\\\o\\}"}, // latin small letter o with stroke, + {"247", "divide", "$\\div$"}, // division sign, U+00F7 ISOnum + {"248", "oslash", "{\\o}"}, // latin small letter o with stroke, // = latin small letter o slash, // U+00F8 ISOlat1 - {"249", "ugrave", "\\{\\\\`\\{u\\}\\}"}, // latin small letter u with grave, + {"249", "ugrave", "{\\`{u}}"}, // latin small letter u with grave, // U+00F9 ISOlat1 - {"250", "uacute", "\\{\\\\'\\{u\\}\\}"}, // latin small letter u with acute, + {"250", "uacute", "{\\'{u}}"}, // latin small letter u with acute, // U+00FA ISOlat1 - {"251", "ucirc", "\\{\\\\\\^\\{u\\}\\}"}, // latin small letter u with circumflex, + {"251", "ucirc", "{\\^{u}}"}, // latin small letter u with circumflex, // U+00FB ISOlat1 - {"252", "uuml", "\\{\\\\\"\\{u\\}\\}"}, // latin small letter u with diaeresis, + {"252", "uuml", "{\\\"{u}}"}, // latin small letter u with diaeresis, // U+00FC ISOlat1 - {"253", "yacute", "\\{\\\\'\\{y\\}\\}"}, // latin small letter y with acute, + {"253", "yacute", "{\\'{y}}"}, // latin small letter y with acute, // U+00FD ISOlat1 - {"254", "thorn", "\\{\\\\th\\}"}, // latin small letter thorn, + {"254", "thorn", "{\\th}"}, // latin small letter thorn, // U+00FE ISOlat1 - {"255", "yuml", "\\{\\\\\"\\{y\\}\\}"}, // latin small letter y with diaeresis, + {"255", "yuml", "{\\\"{y}}"}, // latin small letter y with diaeresis, // U+00FF ISOlat1 - {"332", "Omacro", "\\{\\\\=\\{O\\}\\}"}, // the small letter o with macron - {"333", "omacro", "\\{\\\\=\\{o\\}\\}"}, // the big letter O with macron - {"402", "fnof", "\\$f\\$"}, // latin small f with hook = function + {"332", "Omacro", "{{\\={O}}}"}, // the small letter o with macron + {"333", "omacro", "{\\={o}}"}, // the big letter O with macron + {"402", "fnof", "\textit{f}"}, // latin small f with hook = function // = florin, U+0192 ISOtech /* Greek */ - {"913", "Alpha", "\\{\\$\\\\Alpha\\$\\}"}, // greek capital letter alpha, U+0391 - {"914", "Beta", "\\{\\$\\\\Beta\\$\\}"}, // greek capital letter beta, U+0392 - {"915", "Gamma", "\\{\\$\\\\Gamma\\$\\}"}, // greek capital letter gamma, + {"913", "Alpha", "{{$\\Alpha$}}"}, // greek capital letter alpha, U+0391 + {"914", "Beta", "{$\\Beta$}"}, // greek capital letter beta, U+0392 + {"915", "Gamma", "{$\\Gamma$}"}, // greek capital letter gamma, // U+0393 ISOgrk3 - {"916", "Delta", "\\{\\$\\\\Delta\\$\\}"}, // greek capital letter delta, + {"916", "Delta", "{$\\Delta$}"}, // greek capital letter delta, // U+0394 ISOgrk3 - {"917", "Epsilon", "\\{\\$\\\\Epsilon\\$\\}"}, // greek capital letter epsilon, U+0395 - {"918", "Zeta", "\\{\\$\\\\Zeta\\$\\}"}, // greek capital letter zeta, U+0396 - {"919", "Eta", "\\{\\$\\\\Eta\\$\\}"}, // greek capital letter eta, U+0397 - {"920", "Theta", "\\{\\$\\\\Theta\\$\\}"}, // greek capital letter theta, + {"917", "Epsilon", "{$\\Epsilon$}"}, // greek capital letter epsilon, U+0395 + {"918", "Zeta", "{$\\Zeta$}"}, // greek capital letter zeta, U+0396 + {"919", "Eta", "{$\\Eta$}"}, // greek capital letter eta, U+0397 + {"920", "Theta", "{$\\Theta$}"}, // greek capital letter theta, // U+0398 ISOgrk3 - {"921", "Iota", "\\{\\$\\\\Iota\\$\\}"}, // greek capital letter iota, U+0399 - {"922", "Kappa", "\\{\\$\\\\Kappa\\$\\}"}, // greek capital letter kappa, U+039A - {"923", "Lambda", "\\{\\$\\\\Lambda\\$\\}"}, // greek capital letter lambda, + {"921", "Iota", "{$\\Iota$}"}, // greek capital letter iota, U+0399 + {"922", "Kappa", "{$\\Kappa$}"}, // greek capital letter kappa, U+039A + {"923", "Lambda", "{$\\Lambda$}"}, // greek capital letter lambda, // U+039B ISOgrk3 - {"924", "Mu", "\\{\\$\\\\Mu\\$\\}"}, // greek capital letter mu, U+039C - {"925", "Nu", "\\{\\$\\\\Nu\\$\\}"}, // greek capital letter nu, U+039D - {"926", "Xi", "\\{\\$\\\\Xi\\$\\}"}, // greek capital letter xi, U+039E ISOgrk3 - {"927", "Omicron", "\\{\\$\\\\Omicron\\$\\}"}, // greek capital letter omicron, U+039F - {"928", "Pi", "\\{\\$\\\\Pi\\$\\}"}, // greek capital letter pi, U+03A0 ISOgrk3 - {"929", "Rho", "\\{\\$\\\\Rho\\$\\}"}, // greek capital letter rho, U+03A1 + {"924", "Mu", "{$\\Mu$}"}, // greek capital letter mu, U+039C + {"925", "Nu", "{$\\Nu$}"}, // greek capital letter nu, U+039D + {"926", "Xi", "{$\\Xi$}"}, // greek capital letter xi, U+039E ISOgrk3 + {"927", "Omicron", "{$\\Omicron$}"}, // greek capital letter omicron, U+039F + {"928", "Pi", "{$\\Pi$}"}, // greek capital letter pi, U+03A0 ISOgrk3 + {"929", "Rho", "{$\\Rho$}"}, // greek capital letter rho, U+03A1 /* there is no Sigmaf, and no U+03A2 character either */ - {"931", "Sigma", "\\{\\$\\\\Sigma\\$\\}"}, // greek capital letter sigma, + {"931", "Sigma", "{$\\Sigma$}"}, // greek capital letter sigma, // U+03A3 ISOgrk3 - {"932", "Tau", "\\{\\$\\\\Tau\\$\\}"}, // greek capital letter tau, U+03A4 - {"933", "Upsilon", "\\{\\$\\\\Upsilon\\$\\}"}, // greek capital letter upsilon, + {"932", "Tau", "{$\\Tau$}"}, // greek capital letter tau, U+03A4 + {"933", "Upsilon", "{$\\Upsilon$}"}, // greek capital letter upsilon, // U+03A5 ISOgrk3 - {"934", "Phi", "\\{\\$\\\\Phi\\$\\}"}, // greek capital letter phi, + {"934", "Phi", "{$\\Phi$}"}, // greek capital letter phi, // U+03A6 ISOgrk3 - {"935", "Chi", "\\{\\$\\\\Chi\\$\\}"}, // greek capital letter chi, U+03A7 - {"936", "Psi", "\\{\\$\\\\Psi\\$\\}"}, // greek capital letter psi, + {"935", "Chi", "{$\\Chi$}"}, // greek capital letter chi, U+03A7 + {"936", "Psi", "{$\\Psi$}"}, // greek capital letter psi, // U+03A8 ISOgrk3 - {"937", "Omega", "\\{\\$\\\\Omega\\$\\}"}, // greek capital letter omega, + {"937", "Omega", "{$\\Omega$}"}, // greek capital letter omega, // U+03A9 ISOgrk3 - {"945", "alpha", "\\$\\\\alpha\\$"}, // greek small letter alpha, + {"945", "alpha", "$\\alpha$"}, // greek small letter alpha, // U+03B1 ISOgrk3 - {"946", "beta", "\\$\\\\beta\\$"}, // greek small letter beta, U+03B2 ISOgrk3 - {"947", "gamma", "\\$\\\\gamma\\$"}, // greek small letter gamma, + {"946", "beta", "$\\beta$"}, // greek small letter beta, U+03B2 ISOgrk3 + {"947", "gamma", "$\\gamma$"}, // greek small letter gamma, // U+03B3 ISOgrk3 - {"948", "delta", "\\$\\\\delta\\$"}, // greek small letter delta, + {"948", "delta", "$\\delta$"}, // greek small letter delta, // U+03B4 ISOgrk3 - {"949", "epsilon", "\\$\\\\epsilon\\$"}, // greek small letter epsilon, + {"949", "epsilon", "$\\epsilon$"}, // greek small letter epsilon, // U+03B5 ISOgrk3 - {"950", "zeta", "\\$\\\\zeta\\$"}, // greek small letter zeta, U+03B6 ISOgrk3 - {"951", "eta", "\\$\\\\eta\\$"}, // greek small letter eta, U+03B7 ISOgrk3 - {"952", "theta", "\\$\\\\theta\\$"}, // greek small letter theta, + {"950", "zeta", "$\\zeta$"}, // greek small letter zeta, U+03B6 ISOgrk3 + {"951", "eta", "$\\eta$"}, // greek small letter eta, U+03B7 ISOgrk3 + {"952", "theta", "$\\theta$"}, // greek small letter theta, // U+03B8 ISOgrk3 - {"953", "iota", "\\$\\\\iota\\$"}, // greek small letter iota, U+03B9 ISOgrk3 - {"954", "kappa", "\\$\\\\kappa\\$"}, // greek small letter kappa, + {"953", "iota", "$\\iota$"}, // greek small letter iota, U+03B9 ISOgrk3 + {"954", "kappa", "$\\kappa$"}, // greek small letter kappa, // U+03BA ISOgrk3 - {"955", "lambda", "\\$\\\\lambda\\$"}, // greek small letter lambda, + {"955", "lambda", "$\\lambda$"}, // greek small letter lambda, // U+03BB ISOgrk3 - {"956", "mu", "\\$\\\\mu\\$"}, // greek small letter mu, U+03BC ISOgrk3 - {"957", "nu", "\\$\\\\nu\\$"}, // greek small letter nu, U+03BD ISOgrk3 - {"958", "xi", "\\$\\\\xi\\$"}, // greek small letter xi, U+03BE ISOgrk3 - {"959", "omicron", "\\$\\\\omicron\\$"}, // greek small letter omicron, U+03BF NEW - {"960", "pi", "\\$\\\\phi\\$"}, // greek small letter pi, U+03C0 ISOgrk3 - {"961", "rho", "\\$\\\\rho\\$"}, // greek small letter rho, U+03C1 ISOgrk3 - {"962", "sigmaf", "\\$\\\\varsigma\\$"}, // greek small letter final sigma, + {"956", "mu", "$\\mu$"}, // greek small letter mu, U+03BC ISOgrk3 + {"957", "nu", "$\\nu$"}, // greek small letter nu, U+03BD ISOgrk3 + {"958", "xi", "$\\xi$"}, // greek small letter xi, U+03BE ISOgrk3 + {"959", "omicron", "$\\omicron$"}, // greek small letter omicron, U+03BF NEW + {"960", "pi", "$\\phi$"}, // greek small letter pi, U+03C0 ISOgrk3 + {"961", "rho", "$\\rho$"}, // greek small letter rho, U+03C1 ISOgrk3 + {"962", "sigmaf", "$\\varsigma$"}, // greek small letter final sigma, // U+03C2 ISOgrk3 - {"963", "sigma", "\\$\\\\sigma\\$"}, // greek small letter sigma, + {"963", "sigma", "$\\sigma$"}, // greek small letter sigma, // U+03C3 ISOgrk3 - {"964", "tau", "\\$\\\\tau\\$"}, // greek small letter tau, U+03C4 ISOgrk3 - {"965", "upsilon", "\\$\\\\upsilon\\$"}, // greek small letter upsilon, - {"", "upsi", "\\$\\\\upsilon\\$"}, // alias + {"964", "tau", "$\\tau$"}, // greek small letter tau, U+03C4 ISOgrk3 + {"965", "upsilon", "$\\upsilon$"}, // greek small letter upsilon, + {"", "upsi", "$\\upsilon$"}, // alias // U+03C5 ISOgrk3 - {"966", "phi", "\\$\\\\phi\\$"}, // greek small letter phi, U+03C6 ISOgrk3 - {"967", "chi", "\\$\\\\chi\\$"}, // greek small letter chi, U+03C7 ISOgrk3 - {"968", "psi", "\\$\\\\psi\\$"}, // greek small letter psi, U+03C8 ISOgrk3 - {"969", "omega", "\\$\\\\omega\\$"}, // greek small letter omega, + {"966", "phi", "$\\phi$"}, // greek small letter phi, U+03C6 ISOgrk3 + {"967", "chi", "$\\chi$"}, // greek small letter chi, U+03C7 ISOgrk3 + {"968", "psi", "$\\psi$"}, // greek small letter psi, U+03C8 ISOgrk3 + {"969", "omega", "$\\omega$"}, // greek small letter omega, // U+03C9 ISOgrk3 - {"977", "thetasym", "\\$\\\\vartheta\\$"}, // greek small letter theta symbol, - {"", "thetav", "\\$\\\\vartheta\\$"}, // greek small letter theta symbol, - {"", "vartheta", "\\$\\\\vartheta\\$"}, // greek small letter theta symbol, + {"977", "thetasym", "$\\vartheta$"}, // greek small letter theta symbol, + {"", "thetav", "$\\vartheta$"}, // greek small letter theta symbol, + {"", "vartheta", "$\\vartheta$"}, // greek small letter theta symbol, // U+03D1 NEW - {"978", "upsih", "\\{\\$\\\\Upsilon\\$\\}"}, // greek upsilon with hook symbol, + {"978", "upsih", "{$\\Upsilon$}"}, // greek upsilon with hook symbol, // U+03D2 NEW - {"982", "piv", "\\$\\\\varphi\\$"}, // greek pi symbol, U+03D6 ISOgrk3 + {"982", "piv", "$\\varphi$"}, // greek pi symbol, U+03D6 ISOgrk3 /* General Punctuation */ - {"8226", "bull", "\\$\\\\bullet\\$"}, // bullet = black small circle, + {"8226", "bull", "$\\bullet$"}, // bullet = black small circle, // U+2022 ISOpub /* bullet is NOT the same as bullet operator, U+2219 */ - {"8230", "hellip", "\\{\\\\ldots\\}"}, // horizontal ellipsis = three dot leader, + {"8230", "hellip", "{\\ldots}"}, // horizontal ellipsis = three dot leader, // U+2026 ISOpub - {"8242", "prime", "\\$\\\\prime\\$"}, // prime = minutes = feet, U+2032 ISOtech - {"8243", "Prime", "\\$\\{''\\}\\$"}, // double prime = seconds = inches, + {"8242", "prime", "$\\prime$"}, // prime = minutes = feet, U+2032 ISOtech + {"8243", "Prime", "${''}$"}, // double prime = seconds = inches, // U+2033 ISOtech - {"8254", "oline", "\\{\\\\=\\{\\}\\}"}, // overline = spacing overscore, + {"8254", "oline", "{\\={}}"}, // overline = spacing overscore, // U+203E NEW {"8260", "frasl", "/"}, // fraction slash, U+2044 NEW /* Letterlike Symbols */ - {"8472", "weierp", "\\$\\\\wp\\$"}, // script capital P = power set + {"8472", "weierp", "$\\wp$"}, // script capital P = power set // = Weierstrass p, U+2118 ISOamso - {"8465", "image", "\\{\\$\\\\Im\\$\\}"}, // blackletter capital I = imaginary part, + {"8465", "image", "{$\\Im$}"}, // blackletter capital I = imaginary part, // U+2111 ISOamso - {"8476", "real", "\\{\\$\\\\Re\\$\\}"}, // blackletter capital R = real part symbol, + {"8476", "real", "{$\\Re$}"}, // blackletter capital R = real part symbol, // U+211C ISOamso - {"8482", "trade", "\\{\\\\texttrademark\\}"}, // trade mark sign, U+2122 ISOnum - {"8501", "alefsym", "\\$\\\\aleph\\$"}, // alef symbol = first transfinite cardinal, + {"8482", "trade", "{\\texttrademark}"}, // trade mark sign, U+2122 ISOnum + {"8501", "alefsym", "$\\aleph$"}, // alef symbol = first transfinite cardinal, // U+2135 NEW /* alef symbol is NOT the same as hebrew letter alef, U+05D0 although the same glyph could be used to depict both characters */ /* Arrows */ - {"8592", "larr", "\\$\\\\leftarrow\\$"}, // leftwards arrow, U+2190 ISOnum - {"8593", "uarr", "\\$\\\\uparrow\\$"}, // upwards arrow, U+2191 ISOnum - {"8594", "rarr", "\\$\\\\rightarrow\\$"}, // rightwards arrow, U+2192 ISOnum - {"8595", "darr", "\\$\\\\downarrow\\$"}, // downwards arrow, U+2193 ISOnum - {"8596", "harr", "\\$\\\\leftrightarrow\\$"}, // left right arrow, U+2194 ISOamsa - {"8629", "crarr", "\\$\\\\dlsh\\$"}, // downwards arrow with corner leftwards + {"8592", "larr", "$\\leftarrow$"}, // leftwards arrow, U+2190 ISOnum + {"8593", "uarr", "$\\uparrow$"}, // upwards arrow, U+2191 ISOnum + {"8594", "rarr", "$\\rightarrow$"}, // rightwards arrow, U+2192 ISOnum + {"8595", "darr", "$\\downarrow$"}, // downwards arrow, U+2193 ISOnum + {"8596", "harr", "$\\leftrightarrow$"}, // left right arrow, U+2194 ISOamsa + {"8629", "crarr", "$\\dlsh$"}, // downwards arrow with corner leftwards // = carriage return, U+21B5 NEW - require mathabx - {"8656", "lArr", "\\{\\$\\\\Leftarrow\\$\\}"}, // leftwards double arrow, U+21D0 ISOtech + {"8656", "lArr", "{$\\Leftarrow$}"}, // leftwards double arrow, U+21D0 ISOtech /* ISO 10646 does not say that lArr is the same as the 'is implied by' arrow but also does not have any other character for that function. So ? lArr can be used for 'is implied by' as ISOtech suggests */ - {"8657", "uArr", "\\{\\$\\\\Uparrow\\$\\}"}, // upwards double arrow, U+21D1 ISOamsa - {"8658", "rArr", "\\{\\$\\\\Rightarrow\\$\\}"}, // rightwards double arrow, + {"8657", "uArr", "{$\\Uparrow$}"}, // upwards double arrow, U+21D1 ISOamsa + {"8658", "rArr", "{$\\Rightarrow$}"}, // rightwards double arrow, // U+21D2 ISOtech /* ISO 10646 does not say this is the 'implies' character but does not have another character with this function so ? rArr can be used for 'implies' as ISOtech suggests */ - {"8659", "dArr", "\\{\\$\\\\Downarrow\\$\\}"}, // downwards double arrow, U+21D3 ISOamsa - {"8660", "hArr", "\\{\\$\\\\Leftrightarrow\\$\\}"}, // left right double arrow, + {"8659", "dArr", "{$\\Downarrow$}"}, // downwards double arrow, U+21D3 ISOamsa + {"8660", "hArr", "{$\\Leftrightarrow$}"}, // left right double arrow, // U+21D4 ISOamsa /* Mathematical Operators */ - {"8704", "forall", "\\$\\\\forall\\$"}, // for all, U+2200 ISOtech - {"8706", "part", "\\$\\\\partial\\$"}, // partial differential, U+2202 ISOtech - {"8707", "exist", "\\$\\\\exists\\$"}, // there exists, U+2203 ISOtech - {"8709", "empty", "\\$\\\\emptyset\\$"}, // empty set = null set = diameter, + {"8704", "forall", "$\\forall$"}, // for all, U+2200 ISOtech + {"8706", "part", "$\\partial$"}, // partial differential, U+2202 ISOtech + {"8707", "exist", "$\\exists$"}, // there exists, U+2203 ISOtech + {"8709", "empty", "$\\emptyset$"}, // empty set = null set = diameter, // U+2205 ISOamso - {"8711", "nabla", "\\$\\\\nabla\\$"}, // nabla = backward difference, + {"8711", "nabla", "$\\nabla$"}, // nabla = backward difference, // U+2207 ISOtech - {"8712", "isin", "\\$\\\\in\\$"}, // element of, U+2208 ISOtech - {"8713", "notin", "\\$\\\\notin\\$"}, // not an element of, U+2209 ISOtech - {"8715", "ni", "\\$\\\\ni\\$"}, // contains as member, U+220B ISOtech + {"8712", "isin", "$\\in$"}, // element of, U+2208 ISOtech + {"8713", "notin", "$\\notin$"}, // not an element of, U+2209 ISOtech + {"8715", "ni", "$\\ni$"}, // contains as member, U+220B ISOtech /* should there be a more memorable name than 'ni'? */ - {"8719", "prod", "\\$\\\\prod\\$"}, // n-ary product = product sign, + {"8719", "prod", "$\\prod$"}, // n-ary product = product sign, // U+220F ISOamsb /* prod is NOT the same character as U+03A0 'greek capital letter pi' though the same glyph might be used for both */ - {"8721", "sum", "\\$\\\\sum\\$"}, // n-ary sumation, U+2211 ISOamsb + {"8721", "sum", "$\\sum$"}, // n-ary sumation, U+2211 ISOamsb /* sum is NOT the same character as U+03A3 'greek capital letter sigma' though the same glyph might be used for both */ - {"8722", "minus", "\\$-\\$"}, // minus sign, U+2212 ISOtech - {"8727", "lowast", "\\$\\\\ast\\$"}, // asterisk operator, U+2217 ISOtech - {"8730", "radic", "\\$\\\\sqrt{}\\$"}, // square root = radical sign, + {"8722", "minus", "$-$"}, // minus sign, U+2212 ISOtech + {"8727", "lowast", "$\\ast$"}, // asterisk operator, U+2217 ISOtech + {"8730", "radic", "$\\sqrt{}$"}, // square root = radical sign, // U+221A ISOtech - {"8733", "prop", "\\$\\\\propto\\$"}, // proportional to, U+221D ISOtech - {"8734", "infin", "\\$\\\\infty\\$"}, // infinity, U+221E ISOtech - {"8736", "ang", "\\$\\\\angle\\$"}, // angle, U+2220 ISOamso - {"8743", "and", "\\$\\\\land\\$"}, // logical and = wedge, U+2227 ISOtech - {"8744", "or", "\\$\\\\lor\\$"}, // logical or = vee, U+2228 ISOtech - {"8745", "cap", "\\$\\\\cap\\$"}, // intersection = cap, U+2229 ISOtech - {"8746", "cup", "\\$\\\\cup\\$"}, // union = cup, U+222A ISOtech - {"8747", "int", "\\$\\\\int\\$"}, // integral, U+222B ISOtech - {"8756", "there4", "\\$\\\\uptherefore\\$"}, // therefore, U+2234 ISOtech; only in LaTeX package MnSymbol - {"8764", "sim", "\\$\\\\sim\\$"}, // tilde operator = varies with = similar to, + {"8733", "prop", "$\\propto$"}, // proportional to, U+221D ISOtech + {"8734", "infin", "$\\infty$"}, // infinity, U+221E ISOtech + {"8736", "ang", "$\\angle$"}, // angle, U+2220 ISOamso + {"8743", "and", "$\\land$"}, // logical and = wedge, U+2227 ISOtech + {"8744", "or", "$\\lor$"}, // logical or = vee, U+2228 ISOtech + {"8745", "cap", "$\\cap$"}, // intersection = cap, U+2229 ISOtech + {"8746", "cup", "$\\cup$"}, // union = cup, U+222A ISOtech + {"8747", "int", "$\\int$"}, // integral, U+222B ISOtech + {"8756", "there4", "$\\uptherefore$"}, // therefore, U+2234 ISOtech; only in LaTeX package MnSymbol + {"8764", "sim", "$\\sim$"}, // tilde operator = varies with = similar to, // U+223C ISOtech /* tilde operator is NOT the same character as the tilde, U+007E, although the same glyph might be used to represent both */ - {"8773", "cong", "\\$\\\\cong\\$"}, // approximately equal to, U+2245 ISOtech - {"8776", "asymp", "\\$\\\\approx\\$"}, // almost equal to = asymptotic to, + {"8773", "cong", "$\\cong$"}, // approximately equal to, U+2245 ISOtech + {"8776", "asymp", "$\\approx$"}, // almost equal to = asymptotic to, // U+2248 ISOamsr - {"8800", "ne", "\\$\\\\neq\\$"}, // not equal to, U+2260 ISOtech - {"8801", "equiv", "\\$\\\\equiv\\$"}, // identical to, U+2261 ISOtech - {"8804", "le", "\\$\\\\leq\\$"}, // less-than or equal to, U+2264 ISOtech - {"8805", "ge", "\\$\\\\geq\\$"}, // greater-than or equal to, + {"8800", "ne", "$\\neq$"}, // not equal to, U+2260 ISOtech + {"8801", "equiv", "$\\equiv$"}, // identical to, U+2261 ISOtech + {"8804", "le", "$\\leq$"}, // less-than or equal to, U+2264 ISOtech + {"8805", "ge", "$\\geq$"}, // greater-than or equal to, // U+2265 ISOtech - {"8834", "sub", "\\$\\\\subset\\$"}, // subset of, U+2282 ISOtech - {"8835", "sup", "\\$\\\\supset\\$"}, // superset of, U+2283 ISOtech + {"8834", "sub", "$\\subset$"}, // subset of, U+2282 ISOtech + {"8835", "sup", "$\\supset$"}, // superset of, U+2283 ISOtech /* note that nsup, 'not a superset of, U+2283' is not covered by the Symbol font encoding and is not included. Should it be, for symmetry? It is in ISOamsn */ - {"8836", "nsub", "\\$\\\\nsubset\\$"}, // not a subset of, U+2284 ISOamsn - {"8838", "sube", "\\$\\\\subseteq\\$"}, // subset of or equal to, U+2286 ISOtech - {"8839", "supe", "\\$\\\\supseteq\\$"}, // superset of or equal to, + {"8836", "nsub", "$\\nsubset$"}, // not a subset of, U+2284 ISOamsn + {"8838", "sube", "$\\subseteq$"}, // subset of or equal to, U+2286 ISOtech + {"8839", "supe", "$\\supseteq$"}, // superset of or equal to, // U+2287 ISOtech - {"8853", "oplus", "\\$\\\\oplus\\$"}, // circled plus = direct sum, + {"8853", "oplus", "$\\oplus$"}, // circled plus = direct sum, // U+2295 ISOamsb - {"8855", "otimes", "\\$\\\\otimes\\$"}, // circled times = vector product, + {"8855", "otimes", "$\\otimes$"}, // circled times = vector product, // U+2297 ISOamsb - {"8869", "perp", "\\$\\\\perp\\$"}, // up tack = orthogonal to = perpendicular, + {"8869", "perp", "$\\perp$"}, // up tack = orthogonal to = perpendicular, // U+22A5 ISOtech - {"8901", "sdot", "\\$\\\\cdot\\$"}, // dot operator, U+22C5 ISOamsb + {"8901", "sdot", "$\\cdot$"}, // dot operator, U+22C5 ISOamsb /* dot operator is NOT the same character as U+00B7 middle dot */ - {"8968", "lceil", "\\$\\\\lceil\\$"}, // left ceiling = apl upstile, + {"8968", "lceil", "$\\lceil$"}, // left ceiling = apl upstile, // U+2308 ISOamsc - {"8969", "rceil", "\\$\\\\rceil\\$"}, // right ceiling, U+2309 ISOamsc - {"8970", "lfloor", "\\$\\\\lfloor\\$"}, // left floor = apl downstile, + {"8969", "rceil", "$\\rceil$"}, // right ceiling, U+2309 ISOamsc + {"8970", "lfloor", "$\\lfloor$"}, // left floor = apl downstile, // U+230A ISOamsc - {"8971", "rfloor", "\\$\\\\rfloor\\$"}, // right floor, U+230B ISOamsc + {"8971", "rfloor", "$\\rfloor$"}, // right floor, U+230B ISOamsc /* Miscellaneous Technical */ - {"9001", "lang", "\\$\\\\langle\\$"}, // left-pointing angle bracket = bra, + {"9001", "lang", "$\\langle$"}, // left-pointing angle bracket = bra, // U+2329 ISOtech /* lang is NOT the same character as U+003C 'less than' or U+2039 'single left-pointing angle quotation mark' */ - {"9002", "rang", "\\$\\\\rangle\\$"}, // right-pointing angle bracket = ket, + {"9002", "rang", "$\\rangle$"}, // right-pointing angle bracket = ket, // U+232A ISOtech /* rang is NOT the same character as U+003E 'greater than' or U+203A 'single right-pointing angle quotation mark' */ /* Geometric Shapes */ - {"9674", "loz", "\\$\\\\lozenge\\$"}, // lozenge, U+25CA ISOpub + {"9674", "loz", "$\\lozenge$"}, // lozenge, U+25CA ISOpub /* Miscellaneous Symbols */ - {"9824", "spades", "\\$\\\\spadesuit\\$"}, // black spade suit, U+2660 ISOpub + {"9824", "spades", "$\\spadesuit$"}, // black spade suit, U+2660 ISOpub /* black here seems to mean filled as opposed to hollow */ - {"9827", "clubs", "\\$\\\\clubsuit\\$"}, // black club suit = shamrock, + {"9827", "clubs", "$\\clubsuit$"}, // black club suit = shamrock, // U+2663 ISOpub - {"9829", "hearts", "\\$\\\\heartsuit\\$"}, // black heart suit = valentine, + {"9829", "hearts", "$\\heartsuit$"}, // black heart suit = valentine, // U+2665 ISOpub - {"9830", "diams", "\\$\\\\diamondsuit\\$"}, // black diamond suit, U+2666 ISOpub + {"9830", "diams", "$\\diamondsuit$"}, // black diamond suit, U+2666 ISOpub {"34", "quot", "\""}, // quotation mark = APL quote, // U+0022 ISOnum - {"38", "amp", "\\\\&"}, // ampersand, U+0026 ISOnum - {"60", "lt", "\\$<\\$"}, // less-than sign, U+003C ISOnum - {"62", "gt", "\\$>\\$"}, // greater-than sign, U+003E ISOnum + {"38", "amp", "\\&"}, // ampersand, U+0026 ISOnum + {"60", "lt", "$<$"}, // less-than sign, U+003C ISOnum + {"62", "gt", "$>$"}, // greater-than sign, U+003E ISOnum /* Latin Extended-A */ - {"338", "OElig", "\\{\\\\OE\\}"}, // latin capital ligature OE, + {"338", "OElig", "{{\\OE}}"}, // latin capital ligature OE, // U+0152 ISOlat2 - {"339", "oelig", "\\{\\\\oe\\}"}, // latin small ligature oe, U+0153 ISOlat2 + {"339", "oelig", "{{\\oe}}"}, // latin small ligature oe, U+0153 ISOlat2 /* ligature is a misnomer, this is a separate character in some languages */ - {"352", "Scaron", "\\{\\\\v\\{S\\}\\}"}, // latin capital letter S with caron, + {"352", "Scaron", "{{\\v{S}}}"}, // latin capital letter S with caron, // U+0160 ISOlat2 - {"353", "scaron", "\\{\\\\v\\{s\\}\\}"}, // latin small letter s with caron, + {"353", "scaron", "{\\v{s}}"}, // latin small letter s with caron, // U+0161 ISOlat2 - {"376", "Yuml", "\\{\\\\\"\\{Y\\}\\}"}, // latin capital letter Y with diaeresis, + {"376", "Yuml", "{{\\\"{Y}}}"}, // latin capital letter Y with diaeresis, // U+0178 ISOlat2 /* Spacing Modifier Letters */ - {"710", "circ", "\\{\\\\textasciicircum\\}"}, // modifier letter circumflex accent, + {"710", "circ", "{\\textasciicircum}"}, // modifier letter circumflex accent, // U+02C6 ISOpub - {"732", "tilde", "\\{\\\\textasciitilde\\}"}, // small tilde, U+02DC ISOdia + {"732", "tilde", "{\\textasciitilde}"}, // small tilde, U+02DC ISOdia /* General Punctuation */ - {"8194", "ensp", "\\\\hspace\\{0.5em\\}"}, // en space, U+2002 ISOpub - {"8195", "emsp", "\\\\hspace\\{1em\\}"}, // em space, U+2003 ISOpub - {"8201", "thinsp", "\\\\hspace\\{0.167em\\}"}, // thin space, U+2009 ISOpub - {"8204", "zwnj", ""}, // zero width non-joiner, + {"8194", "ensp", "\\hspace{0.5em}"}, // en space, U+2002 ISOpub + {"8195", "emsp", "\\hspace{1em}"}, // em space, U+2003 ISOpub + {"8201", "thinsp", "\\hspace{0.167em}"}, // thin space, U+2009 ISOpub + {"8204", "zwnj", "\\/{}"}, // zero width non-joiner, // U+200C NEW RFC 2070 {"8205", "zwj", ""}, // zero width joiner, U+200D NEW RFC 2070 {"8206", "lrm", ""}, // left-to-right mark, U+200E NEW RFC 2070 {"8207", "rlm", ""}, // right-to-left mark, U+200F NEW RFC 2070 {"8211", "ndash", "--"}, // en dash, U+2013 ISOpub {"8212", "mdash", "---"}, // em dash, U+2014 ISOpub - {"8216", "lsquo", "\\{\\\\textquoteleft\\}"}, // left single quotation mark, + {"8216", "lsquo", "{\\textquoteleft}"}, // left single quotation mark, // U+2018 ISOnum - {"8217", "rsquo", "\\{\\\\textquoteright\\}"}, // right single quotation mark, + {"8217", "rsquo", "{\\textquoteright}"}, // right single quotation mark, // U+2019 ISOnum - {"8218", "sbquo", "\\{\\\\quotesinglbase\\}"}, // single low-9 quotation mark, U+201A NEW - {"8220", "ldquo", "\\{\\\\textquotedblleft\\}"}, // left double quotation mark, + {"8218", "sbquo", "{\\quotesinglbase}"}, // single low-9 quotation mark, U+201A NEW + {"8220", "ldquo", "{\\textquotedblleft}"}, // left double quotation mark, // U+201C ISOnum - {"8221", "rdquo", "\\{\\\\textquotedblright\\}"}, // right double quotation mark, + {"8221", "rdquo", "{\\textquotedblright}"}, // right double quotation mark, // U+201D ISOnum - {"8222", "bdquo", "\\{\\\\quotedblbase\\}"}, // double low-9 quotation mark, U+201E NEW - {"8224", "dagger", "\\{\\\\dag\\}"}, // dagger, U+2020 ISOpub - {"8225", "Dagger", "\\{\\\\ddag\\}"}, // double dagger, U+2021 ISOpub - {"8240", "permil", "\\{\\\\textperthousand\\}"}, // per mille sign, U+2030 ISOtech - {"8249", "lsaquo", "\\{\\\\guilsinglleft\\}"}, // single left-pointing angle quotation mark, + {"8222", "bdquo", "{\\quotedblbase}"}, // double low-9 quotation mark, U+201E NEW + {"8224", "dagger", "{\\dag}"}, // dagger, U+2020 ISOpub + {"8225", "Dagger", "{\\ddag}"}, // double dagger, U+2021 ISOpub + {"8240", "permil", "{\\textperthousand}"}, // per mille sign, U+2030 ISOtech + {"8249", "lsaquo", "{\\guilsinglleft}"}, // single left-pointing angle quotation mark, // U+2039 ISO proposed /* lsaquo is proposed but not yet ISO standardized */ - {"8250", "rsaquo", "\\{\\\\guilsinglright\\}"}, // single right-pointing angle quotation mark, + {"8250", "rsaquo", "{\\guilsinglright}"}, // single right-pointing angle quotation mark, // U+203A ISO proposed /* rsaquo is proposed but not yet ISO standardized */ - {"8364", "euro", "\\{\\\\texteuro\\}"}, // euro sign, U+20AC NEW + {"8364", "euro", "{\\texteuro}"}, // euro sign, U+20AC NEW /* Manually added */ - {"35", "", "\\\\#"}, // Hash - {"36", "dollar", "\\\\$"}, // Dollar - {"37", "percnt", "\\\\%"}, // Percent + {"35", "", "\\#"}, // Hash + {"36", "dollar", "\\$"}, // Dollar + {"37", "percnt", "\\%"}, // Percent {"39", "apos", "'"}, // Apostrophe {"40", "lpar", "("}, // Left bracket {"41", "rpar", ")"}, // Right bracket @@ -496,177 +496,177 @@ public class HTMLUnicodeConversionMaps { {"58", "colon", ":"}, // Colon {"59", "semi", ";"}, // Semi colon {"61", "equals", "="}, // Equals to - {"91", "lsqb", "\\["}, // Left square bracket - {"92", "bsol", "\\{\\\\textbackslash\\}"}, // Backslash - {"93", "rsqb", "\\]"}, // Right square bracket - {"94", "Hat", "\\{\\\\\\^\\{\\}\\}"}, // Circumflex - {"95", "lowbar", "\\\\_"}, // Underscore - {"96", "grave", "\\{\\\\`\\{\\}\\}"}, // Grave - {"123", "lbrace", "\\\\\\{"}, // Left curly bracket - {"", "lcub", "\\\\\\{"}, // Left curly bracket - {"124", "vert", "\\|"}, // Vertical bar - {"", "verbar", "\\|"}, // Vertical bar - {"", "VerticalLine", "\\|"}, // Vertical bar - {"125", "rbrace", "\\\\\\}"}, // Right curly bracket - {"", "rcub", "\\\\\\}"}, // Right curly bracket - {"138", "", "\\{\\\\v\\{S\\}\\}"}, // Line tabulation set + {"91", "lsqb", "["}, // Left square bracket + {"92", "bsol", "{\\textbackslash}"}, // Backslash + {"93", "rsqb", "]"}, // Right square bracket + {"94", "Hat", "{\\^{}}"}, // Circumflex + {"95", "lowbar", "\\_"}, // Underscore + {"96", "grave", "{\\`{}}"}, // Grave + {"123", "lbrace", "\\{"}, // Left curly bracket + {"", "lcub", "\\{"}, // Left curly bracket + {"124", "vert", "|"}, // Vertical bar + {"", "verbar", "|"}, // Vertical bar + {"", "VerticalLine", "|"}, // Vertical bar + {"125", "rbrace", "\\}"}, // Right curly bracket + {"", "rcub", "\\}"}, // Right curly bracket + {"138", "", "{{\\v{S}}}"}, // Line tabulation set // {"141", "", ""}, // Reverse line feed {"145", "", "`"}, // Apostrophe {"146", "", "'"}, // Apostrophe {"147", "", "``"}, // Quotation mark {"148", "", "''"}, // Quotation mark {"150", "", "--"}, // En dash - {"154", "", "\\{\\\\v\\{s\\}\\}"}, // Single character introducer - {"260", "Aogon", "\\{\\\\k\\{A\\}\\}"}, // capital A with ogonek - {"261", "aogon", "\\{\\\\k\\{a\\}\\}"}, // small a with ogonek - {"262", "Cacute", "\\{\\\\'\\{C\\}\\}"}, // capital C with acute - {"263", "cacute", "\\{\\\\'\\{c\\}\\}"}, // small C with acute - {"264", "Ccirc", "\\{\\\\\\^\\{C\\}\\}"}, // capital C with circumflex - {"265", "ccirc", "\\{\\\\\\^\\{c\\}\\}"}, // small C with circumflex - {"266", "Cdot", "\\{\\\\\\.\\{C\\}\\}"}, // capital C with dot above - {"267", "cdot", "\\{\\\\\\.\\{c\\}\\}"}, // small C with dot above - {"268", "Ccaron", "\\{\\\\v\\{C\\}\\}"}, // capital C with caron - {"269", "ccaron", "\\{\\\\v\\{c\\}\\}"}, // small C with caron - {"272", "Dstrok", "\\{\\\\DJ\\}"}, // capital D with stroke - {"273", "dstrok", "\\{\\\\dj\\}"}, // small d with stroke - {"280", "Eogon", "\\{\\\\k\\{E\\}\\}"}, // capital E with ogonek - {"281", "eogon", "\\{\\\\k\\{e\\}\\}"}, // small e with ogonek - {"298", "Imacr", "\\{\\\\=\\{I\\}\\}"}, // capital I with macron - {"299", "imacr", "\\{\\\\=\\{\\\\i\\}\\}"}, // small i with macron - {"302", "Iogon", "\\{\\\\k\\{I\\}\\}"}, // capital I with ogonek - {"303", "iogon", "\\{\\\\k\\{i\\}\\}"}, // small i with ogonek - {"304", "Idot", "\\{\\\\.\\{I\\}\\}"}, // capital I with dot above - {"305", "inodot", "\\{\\\\i\\}"}, // Small i without the dot - {"", "imath", "\\{\\\\i\\}"}, // Small i without the dot - {"306", "", "\\{\\\\IJ\\}"}, // Dutch di-graph IJ - {"307", "", "\\{\\\\ij\\}"}, // Dutch di-graph ij - {"312", "", "\\{\\\\textkra\\}"}, // Letter kra - {"319", "Lmidot", "\\{\\\\Lmidot\\}"}, // upper case L with mid dot - {"320", "lmidot", "\\{\\\\lmidot\\}"}, // lower case l with stroke - {"321", "Lstrok", "\\{\\\\L\\}"}, // upper case L with stroke - {"322", "lstrok", "\\{\\\\l\\}"}, // lower case l with stroke - {"330", "", "\\{\\\\NG\\}"}, // upper case letter Eng - {"331", "", "\\{\\\\ng\\}"}, // lower case letter Eng - {"338", "", "\\{\\\\OE\\}"}, // OE-ligature - {"339", "", "\\{\\\\oe\\}"}, // oe-ligature - {"348", "Scirc", "\\{\\\\\\^\\{S\\}\\}"}, // upper case S with circumflex - {"349", "scirc", "\\{\\\\\\^\\{s\\}\\}"}, // lower case s with circumflex - {"370", "Uogon", "\\{\\\\k\\{U\\}\\}"}, // capital U with ogonek - {"371", "uogon", "\\{\\\\k\\{u\\}\\}"}, // small u with ogonek - {"381", "Zcaron", "\\{\\\\v\\{Z\\}\\}"}, // capital Z with caron - {"382", "zcaron", "\\{\\\\v\\{z\\}\\}"}, // small z with caron - {"405", "", "\\{\\\\hv\\}"}, // small letter Hv - {"416", "", "\\{\\\\OHORN\\}"}, // capital O with horn - {"417", "", "\\{\\\\ohorn\\}"}, // small o with horn - {"431", "", "\\{\\\\UHORN\\}"}, // capital U with horn - {"432", "", "\\{\\\\uhorn\\}"}, // small u with horn - {"490", "Oogon", "\\{\\\\k\\{O\\}\\}"}, // capital letter O with ogonek - {"491", "oogon", "\\{\\\\k\\{o\\}\\}"}, // small letter o with ogonek - {"492", "", "\\{\\\\k\\{\\\\=\\{O\\}\\}\\}"}, // capital letter O with ogonek and macron - {"493", "", "\\{\\\\k\\{\\\\=\\{o\\}\\}\\}"}, // small letter o with ogonek and macron - {"536", "", "\\{\\\\cb\\{S\\}\\}"}, // capital letter S with comma below, require combelow - {"537", "", "\\{\\\\cb\\{s\\}\\}"}, // small letter S with comma below, require combelow - {"538", "", "\\{\\\\cb\\{T\\}\\}"}, // capital letter T with comma below, require combelow - {"539", "", "\\{\\\\cb\\{t\\}\\}"}, // small letter T with comma below, require combelow - {"727", "caron", "\\{\\\\v\\{\\}\\}"}, // Caron - {"", "Hacek", "\\{\\\\v\\{\\}\\}"}, // Caron - {"728", "breve", "\\{\\\\u\\{\\}\\}"}, // Breve - {"", "Breve", "\\{\\\\u\\{\\}\\}"}, // Breve - {"729", "dot", "\\{\\\\\\.\\{\\}\\}"}, // Dot above - {"730", "ring", "\\{\\\\r\\{\\}\\}"}, // Ring above - {"731", "ogon", "\\{\\\\k\\{\\}\\}"}, // Ogonek - {"733", "dblac", "\\{\\\\H\\{\\}\\}"}, // Double acute - {"949", "epsi", "\\$\\\\epsilon\\$"}, // Epsilon - double check - {"1013", "epsiv", "\\$\\\\varepsilonup\\$"}, // lunate epsilon, requires txfonts - {"1055", "", "\\{\\\\cyrchar\\\\CYRP\\}"}, // Cyrillic capital Pe - {"1082", "", "\\{\\\\cyrchar\\\\cyrk\\}"}, // Cyrillic small Ka + {"154", "", "{\\v{s}}"}, // Single character introducer + {"260", "Aogon", "{{\\k{A}}}"}, // capital A with ogonek + {"261", "aogon", "{\\k{a}}"}, // small a with ogonek + {"262", "Cacute", "{{\\'{C}}}"}, // capital C with acute + {"263", "cacute", "{\\'{c}}"}, // small C with acute + {"264", "Ccirc", "{{\\^{C}}}"}, // capital C with circumflex + {"265", "ccirc", "{\\^{c}}"}, // small C with circumflex + {"266", "Cdot", "{{\\\\.{C}}}"}, // capital C with dot above + {"267", "cdot", "{\\\\.{c}}"}, // small C with dot above + {"268", "Ccaron", "{{\\v{C}}}"}, // capital C with caron + {"269", "ccaron", "{\\v{c}}"}, // small C with caron + {"272", "Dstrok", "{{\\DJ}}"}, // capital D with stroke + {"273", "dstrok", "{{\\dj}}"}, // small d with stroke + {"280", "Eogon", "{{\\k{E}}}"}, // capital E with ogonek + {"281", "eogon", "{\\k{e}}"}, // small e with ogonek + {"298", "Imacr", "{{\\={I}}}"}, // capital I with macron + {"299", "imacr", "{\\={\\i}}"}, // small i with macron + {"302", "Iogon", "{{\\k{I}}}"}, // capital I with ogonek + {"303", "iogon", "{\\k{i}}"}, // small i with ogonek + {"304", "Idot", "{{\\.{I}}}"}, // capital I with dot above + {"305", "inodot", "{\\i}"}, // Small i without the dot + {"", "imath", "{\\i}"}, // Small i without the dot + {"306", "", "{{\\IJ}}"}, // Dutch di-graph IJ + {"307", "", "{{\\ij}}"}, // Dutch di-graph ij + {"312", "", "{\\textkra}"}, // Letter kra + {"319", "Lmidot", "{\\Lmidot}"}, // upper case L with mid dot + {"320", "lmidot", "{\\lmidot}"}, // lower case l with stroke + {"321", "Lstrok", "{{\\L}}"}, // upper case L with stroke + {"322", "lstrok", "{{\\l}}"}, // lower case l with stroke + {"330", "", "{{\\NG}}"}, // upper case letter Eng + {"331", "", "{{\\ng}}"}, // lower case letter Eng + {"338", "", "{{\\OE}}"}, // OE-ligature + {"339", "", "{{\\oe}}"}, // oe-ligature + {"348", "Scirc", "{{\\^{S}}}"}, // upper case S with circumflex + {"349", "scirc", "{\\^{s}}"}, // lower case s with circumflex + {"370", "Uogon", "{{\\k{U}}}"}, // capital U with ogonek + {"371", "uogon", "{\\k{u}}"}, // small u with ogonek + {"381", "Zcaron", "{{\\v{Z}}}"}, // capital Z with caron + {"382", "zcaron", "{\\v{z}}"}, // small z with caron + {"405", "", "{{\\hv}}"}, // small letter Hv + {"416", "", "{{\\OHORN}}"}, // capital O with horn + {"417", "", "{{\\ohorn}}"}, // small o with horn + {"431", "", "{{\\UHORN}}"}, // capital U with horn + {"432", "", "{{\\uhorn}}"}, // small u with horn + {"490", "Oogon", "{{\\k{O}}}"}, // capital letter O with ogonek + {"491", "oogon", "{\\k{o}}"}, // small letter o with ogonek + {"492", "", "{{\\k{\\={O}}}}"}, // capital letter O with ogonek and macron + {"493", "", "{\\k{\\={o}}}"}, // small letter o with ogonek and macron + {"536", "", "{{\\cb{S}}}"}, // capital letter S with comma below, require combelow + {"537", "", "{\\cb{s}}"}, // small letter S with comma below, require combelow + {"538", "", "{{\\cb{T}}}"}, // capital letter T with comma below, require combelow + {"539", "", "{\\cb{t}}"}, // small letter T with comma below, require combelow + {"727", "caron", "{\\v{}}"}, // Caron + {"", "Hacek", "{\\v{}}"}, // Caron + {"728", "breve", "{\\u{}}"}, // Breve + {"", "Breve", "{\\u{}}"}, // Breve + {"729", "dot", "{\\\\.{}}"}, // Dot above + {"730", "ring", "{\\r{}}"}, // Ring above + {"731", "ogon", "{\\k{}}"}, // Ogonek + {"733", "dblac", "{\\H{}}"}, // Double acute + {"949", "epsi", "$\\epsilon$"}, // Epsilon - double check + {"1013", "epsiv", "$\\varepsilonup$"}, // lunate epsilon, requires txfonts + {"1055", "", "{\\cyrchar\\CYRP}"}, // Cyrillic capital Pe + {"1082", "", "{\\cyrchar\\cyrk}"}, // Cyrillic small Ka // {"2013", "", ""}, // NKO letter FA -- Maybe en dash = 0x2013? // {"2014", "", ""}, // NKO letter FA -- Maybe em dash = 0x2014? - {"8192", "", "\\\\hspace\\{0.5em\\}"}, // en quad - {"8193", "", "\\\\hspace\\{1em\\}"}, // em quad - {"8196", "", "\\\\hspace\\{0.333em\\}"}, // Three-Per-Em Space - {"8197", "", "\\\\hspace\\{0.25em\\}"}, // Four-Per-Em Space - {"8198", "", "\\\\hspace\\{0.167em\\}"}, // Six-Per-Em Space + {"8192", "", "\\hspace{0.5em}"}, // en quad + {"8193", "", "\\hspace{1em}"}, // em quad + {"8196", "", "\\hspace{0.333em}"}, // Three-Per-Em Space + {"8197", "", "\\hspace{0.25em}"}, // Four-Per-Em Space + {"8198", "", "\\hspace{0.167em}"}, // Six-Per-Em Space {"8208", "hyphen", "-"}, // Hyphen {"8229", "nldr", "\\.\\."}, // Double dots - en leader - {"8241", "", "\\{\\\\textpertenthousand\\}"}, // per ten thousands sign - {"8244", "", "\\{\\\\prime\\\\prime\\\\prime\\}"}, // triple prime - {"8251", "", "\\{\\\\textreferencemark\\}"}, {"8253", "", "\\{\\\\textinterrobang\\}"}, - {"8450", "complexes", "\\$\\\\mathbb\\{C\\}\\$"}, // double struck capital C -- requires e.g. amsfonts - {"8451", "", "\\$\\\\deg\\$\\{C\\}"}, // Degree Celsius - {"8459", "Hscr", "\\$\\\\mathcal\\{H\\}\\$"}, // script capital H -- possibly use \mathscr - {"8460", "Hfr", "\\$\\\\mathbb\\{H\\}\\$"}, // black letter capital H -- requires e.g. amsfonts - {"8466", "Lscr", "\\$\\\\mathcal\\{L\\}\\$"}, // script capital L -- possibly use \mathscr - {"8467", "ell", "\\{\\\\ell\\}"}, // script small l - {"8469", "naturals", "\\$\\\\mathbb\\{N\\}\\$"}, // double struck capital N -- requires e.g. amsfonts - {"8474", "Qopf", "\\$\\\\mathbb\\{Q\\}\\$"}, // double struck capital Q -- requires e.g. amsfonts - {"8477", "reals", "\\$\\\\mathbb\\{R\\}\\$"}, // double struck capital R -- requires e.g. amsfonts - {"8486", "", "\\$\\{\\\\Omega\\}\\$"}, // Omega - {"8491", "angst", "\\{\\\\AA\\}"}, // Angstrom - {"8496", "Escr", "\\$\\\\mathcal\\{E\\}\\$"}, // script capital E - {"8531", "frac13", "\\$\\\\sfrac\\{1\\}\\{3\\}\\$"}, // Vulgar fraction one third - {"8532", "frac23", "\\$\\\\sfrac\\{2\\}\\{3\\}\\$"}, // Vulgar fraction two thirds - {"8533", "frac15", "\\$\\\\sfrac\\{1\\}\\{5\\}\\$"}, // Vulgar fraction one fifth - {"8534", "frac25", "\\$\\\\sfrac\\{2\\}\\{5\\}\\$"}, // Vulgar fraction two fifths - {"8535", "frac35", "\\$\\\\sfrac\\{3\\}\\{5\\}\\$"}, // Vulgar fraction three fifths - {"8536", "frac45", "\\$\\\\sfrac\\{4\\}\\{5\\}\\$"}, // Vulgar fraction four fifths - {"8537", "frac16", "\\$\\\\sfrac\\{1\\}\\{6\\}\\$"}, // Vulgar fraction one sixth - {"8538", "frac56", "\\$\\\\sfrac\\{5\\}\\{6\\}\\$"}, // Vulgar fraction five sixths - {"8539", "frac18", "\\$\\\\sfrac\\{1\\}\\{8\\}\\$"}, // Vulgar fraction one eighth - {"8540", "frac38", "\\$\\\\sfrac\\{3\\}\\{8\\}\\$"}, // Vulgar fraction three eighths - {"8541", "frac58", "\\$\\\\sfrac\\{5\\}\\{8\\}\\$"}, // Vulgar fraction five eighths - {"8542", "frac78", "\\$\\\\sfrac\\{7\\}\\{8\\}\\$"}, // Vulgar fraction seven eighths - {"8710", "", "\\$\\\\triangle\\$"}, // Increment - could use a more appropriate symbol - {"8714", "", "\\$\\\\in\\$"}, // Small element in - {"8723", "mp", "\\$\\\\mp\\$"}, // Minus-plus - {"8729", "bullet", "\\$\\\\bullet\\$"}, // Bullet operator + {"8241", "", "{\\textpertenthousand}"}, // per ten thousands sign + {"8244", "", "{\\prime\\prime\\prime}"}, // triple prime + {"8251", "", "{\\textreferencemark}"}, {"8253", "", "{\\textinterrobang}"}, + {"8450", "complexes", "$\\mathbb{C}$"}, // double struck capital C -- requires e.g. amsfonts + {"8451", "", "$\\deg${C}"}, // Degree Celsius + {"8459", "Hscr", "$\\mathcal{H}$"}, // script capital H -- possibly use \mathscr + {"8460", "Hfr", "$\\mathbb{H}$"}, // black letter capital H -- requires e.g. amsfonts + {"8466", "Lscr", "$\\mathcal{L}$"}, // script capital L -- possibly use \mathscr + {"8467", "ell", "{\\ell}"}, // script small l + {"8469", "naturals", "$\\mathbb{N}$"}, // double struck capital N -- requires e.g. amsfonts + {"8474", "Qopf", "$\\mathbb{Q}$"}, // double struck capital Q -- requires e.g. amsfonts + {"8477", "reals", "$\\mathbb{R}$"}, // double struck capital R -- requires e.g. amsfonts + {"8486", "", "${\\Omega}$"}, // Omega + {"8491", "angst", "{{\\AA}}"}, // Angstrom + {"8496", "Escr", "$\\mathcal{E}$"}, // script capital E + {"8531", "frac13", "$\\sfrac{1}{3}$"}, // Vulgar fraction one third + {"8532", "frac23", "$\\sfrac{2}{3}$"}, // Vulgar fraction two thirds + {"8533", "frac15", "$\\sfrac{1}{5}$"}, // Vulgar fraction one fifth + {"8534", "frac25", "$\\sfrac{2}{5}$"}, // Vulgar fraction two fifths + {"8535", "frac35", "$\\sfrac{3}{5}$"}, // Vulgar fraction three fifths + {"8536", "frac45", "$\\sfrac{4}{5}$"}, // Vulgar fraction four fifths + {"8537", "frac16", "$\\sfrac{1}{6}$"}, // Vulgar fraction one sixth + {"8538", "frac56", "$\\sfrac{5}{6}$"}, // Vulgar fraction five sixths + {"8539", "frac18", "$\\sfrac{1}{8}$"}, // Vulgar fraction one eighth + {"8540", "frac38", "$\\sfrac{3}{8}$"}, // Vulgar fraction three eighths + {"8541", "frac58", "$\\sfrac{5}{8}$"}, // Vulgar fraction five eighths + {"8542", "frac78", "$\\sfrac{7}{8}$"}, // Vulgar fraction seven eighths + {"8710", "", "$\\triangle$"}, // Increment - could use a more appropriate symbol + {"8714", "", "$\\in$"}, // Small element in + {"8723", "mp", "$\\mp$"}, // Minus-plus + {"8729", "bullet", "$\\bullet$"}, // Bullet operator {"8758", "ratio", ":"}, // Colon/ratio - {"8771", "sime", "\\$\\\\simeq\\$"}, // almost equal to = asymptotic to, - {"8776", "ap", "\\$\\\\approx\\$"}, // almost equal to = asymptotic to, - {"8810", "ll", "\\$\\\\ll\\$"}, // Much less than - {"", "Lt", "\\$\\\\ll\\$"}, // Much less than - {"8811", "gg", "\\$\\\\gg\\$"}, // Much greater than - {"", "Gt", "\\$\\\\gg\\$"}, // Much greater than - {"8818", "lsim", "\\$\\\\lesssim\\$"}, // Less than or equivalent to - {"8819", "gsim", "\\$\\\\gtrsim\\$"}, // Greater than or equivalent to - {"8862", "boxplus", "\\$\\\\boxplus\\$"}, // Boxed plus -- requires amssymb - {"8863", "boxminus", "\\$\\\\boxminus\\$"}, // Boxed minus -- requires amssymb - {"8864", "boxtimes", "\\$\\\\boxtimes\\$"}, // Boxed times -- requires amssymb - {"8882", "vltri", "\\$\\\\triangleleft\\$"}, // Left triangle - {"8883", "vrtri", "\\$\\\\triangleright\\$"}, // Right triangle - {"8896", "xwedge", "\\$\\\\bigwedge\\$"}, // Big wedge - {"8897", "xvee", "\\$\\\\bigvee\\$"}, // Big vee - {"8942", "vdots", "\\$\\\\vdots\\$"}, // vertical ellipsis U+22EE - {"8943", "cdots", "\\$\\\\cdots\\$"}, // midline horizontal ellipsis U+22EF - /*{"8944", "", "\\$\\\\ddots\\$"}, // up right diagonal ellipsis U+22F0 */ - {"8945", "ddots", "\\$\\\\ddots\\$"}, // down right diagonal ellipsis U+22F1 + {"8771", "sime", "$\\simeq$"}, // almost equal to = asymptotic to, + {"8776", "ap", "$\\approx$"}, // almost equal to = asymptotic to, + {"8810", "ll", "$\\ll$"}, // Much less than + {"", "Lt", "$\\ll$"}, // Much less than + {"8811", "gg", "$\\gg$"}, // Much greater than + {"", "Gt", "$\\gg$"}, // Much greater than + {"8818", "lsim", "$\\lesssim$"}, // Less than or equivalent to + {"8819", "gsim", "$\\gtrsim$"}, // Greater than or equivalent to + {"8862", "boxplus", "$\\boxplus$"}, // Boxed plus -- requires amssymb + {"8863", "boxminus", "$\\boxminus$"}, // Boxed minus -- requires amssymb + {"8864", "boxtimes", "$\\boxtimes$"}, // Boxed times -- requires amssymb + {"8882", "vltri", "$\\triangleleft$"}, // Left triangle + {"8883", "vrtri", "$\\triangleright$"}, // Right triangle + {"8896", "xwedge", "$\\bigwedge$"}, // Big wedge + {"8897", "xvee", "$\\bigvee$"}, // Big vee + {"8942", "vdots", "$\\vdots$"}, // vertical ellipsis U+22EE + {"8943", "cdots", "$\\cdots$"}, // midline horizontal ellipsis U+22EF + /*{"8944", "", "$\\ddots$"}, // up right diagonal ellipsis U+22F0 */ + {"8945", "ddots", "$\\ddots$"}, // down right diagonal ellipsis U+22F1 - {"9426", "circledc", "\\{\\\\copyright\\}"}, // circled small letter C - {"9633", "square", "\\$\\\\square\\$"}, // White square - {"9651", "xutri", "\\$\\\\bigtriangleup\\$"}, // White up-pointing big triangle - {"9653", "utri", "\\$\\\\triangle\\$"}, // White up-pointing small triangle -- \vartriangle probably + {"9426", "circledc", "{\\copyright}"}, // circled small letter C + {"9633", "square", "$\\square$"}, // White square + {"9651", "xutri", "$\\bigtriangleup$"}, // White up-pointing big triangle + {"9653", "utri", "$\\triangle$"}, // White up-pointing small triangle -- \vartriangle probably // better but requires amssymb - {"10877", "les", "\\$\\\\leqslant\\$"}, // Less than slanted equal -- requires amssymb - {"10878", "ges", "\\$\\\\geqslant\\$"}, // Less than slanted equal -- requires amssymb - {"119978", "Oscr", "\\$\\\\mathcal\\{O\\}\\$"}, // script capital O -- possibly use \mathscr - {"119984", "Uscr", "\\$\\\\mathcal\\{U\\}\\$"} // script capital U -- possibly use \mathscr + {"10877", "les", "$\\leqslant$"}, // Less than slanted equal -- requires amssymb + {"10878", "ges", "$\\geqslant$"}, // Less than slanted equal -- requires amssymb + {"119978", "Oscr", "$\\mathcal{O}$"}, // script capital O -- possibly use \mathscr + {"119984", "Uscr", "$\\mathcal{U}$"} // script capital U -- possibly use \mathscr }; // List of combining accents private static final String[][] ACCENT_LIST = new String[][] {{"768", "`"}, // Grave {"769", "'"}, // Acute - {"770", "\\^"}, // Circumflex + {"770", "^"}, // Circumflex {"771", "~"}, // Tilde {"772", "="}, // Macron {"773", "="}, // Overline - not completely correct {"774", "u"}, // Breve - {"775", "\\."}, // Dot above + {"775", "."}, // Dot above {"776", "\""}, // Diaeresis {"777", "h"}, // Hook above {"778", "r"}, // Ring {"779", "H"}, // Double acute {"780", "v"}, // Caron - {"781", "\\|"}, // Vertical line above + {"781", "|"}, // Vertical line above {"782", "U"}, // Double vertical line above {"783", "G"}, // Double grave {"784", "textdotbreve"}, // Candrabindu From 17262c18d67571b561dd588793ed1c6fbdd0c093 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 19 Apr 2016 21:52:37 +0200 Subject: [PATCH 119/268] Added double {} around all symbols with capital letters to avoid lowercasing in titles. Fixed #405 --- CHANGELOG.md | 3 + .../net/sf/jabref/benchmarks/Benchmarks.java | 53 +++--------- .../strings/HTMLUnicodeConversionMaps.java | 84 +++++++++---------- .../logic/cleanup/CleanupWorkerTest.java | 2 +- .../HtmlToLatexFormatterTest.java | 2 +- .../bibtexfields/UnicodeConverterTest.java | 2 +- 6 files changed, 59 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b5ee6600ff6..95086a17d8d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,7 +138,10 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - [#969](https://github.com/JabRef/jabref/issues/969) Adding and replacing old event system mechanisms with Google Guava EventBus. ### Fixed +<<<<<<< 973a39d9fa61ad9149db778e27112ecaeb13d712 - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file +======= +>>>>>>> Added double {} around all symbols with capital letters to avoid lowercasing in titles. Fixed #405 - Fixed [#318](https://github.com/JabRef/jabref/issues/318): Improve normalization of author names - Fixed [#598](https://github.com/JabRef/jabref/issues/598) and [#402](https://github.com/JabRef/jabref/issues/402): No more issues with invalid icons for ExternalFileTypes in global search or after editing the settings - Fixed [#883](https://github.com/JabRef/jabref/issues/883): No NPE during cleanup diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index 6a391a6fa904..bfd53437312e 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -22,7 +22,6 @@ import net.sf.jabref.logic.layout.format.HTMLChars; import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; import net.sf.jabref.logic.search.SearchQuery; -import net.sf.jabref.logic.util.strings.HTMLUnicodeConversionMaps; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.database.BibDatabaseModeDetection; @@ -40,8 +39,8 @@ public class Benchmarks { private String bibtexString; private final BibDatabase database = new BibDatabase(); - private final List latexConversionStrings = new ArrayList<>(); - private final List htmlConversionStrings = new ArrayList<>(); + private String latexConversionString; + private String htmlConversionString; @Setup public void init() throws IOException, SaveException { @@ -66,27 +65,9 @@ public void init() throws IOException, SaveException { new SavePreferences()); bibtexString = stringWriter.toString(); - List latexSymbols = new ArrayList<>(HTMLUnicodeConversionMaps.UNICODE_LATEX_CONVERSION_MAP.values()); - int symbolcount = latexSymbols.size(); - StringBuilder sb = new StringBuilder(); - sb.append("{A} \\textbf{bold} "); - sb.append(latexSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); - sb.append(" {\\it italic} {"); - sb.append(latexSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); - sb.append(latexSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); - sb.append("} abc"); - latexConversionStrings.add(sb.toString()); - - List htmlSymbols = new ArrayList<>(HTMLUnicodeConversionMaps.HTML_LATEX_CONVERSION_MAP.keySet()); - symbolcount = htmlSymbols.size(); - sb = new StringBuilder(); - sb.append("A bold "); - sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); - sb.append(" italic "); - sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); - sb.append(htmlSymbols.get(Math.abs(randomizer.nextInt() % symbolcount))); - sb.append("– abc"); - htmlConversionStrings.add(sb.toString()); + latexConversionString = "{A} \\textbf{bold} approach {\\it to} ${{\\Sigma}}{\\Delta}$ modulator \\textsuperscript{2} \\$"; + + htmlConversionString = "Österreich – & characters ⪢ italic"; } @Benchmark @@ -122,33 +103,21 @@ public BibDatabaseMode inferBibDatabaseMode() { } @Benchmark - public List latexToUnicodeConversion() { - List result = new ArrayList<>(1000); + public String latexToUnicodeConversion() { LatexToUnicodeFormatter f = new LatexToUnicodeFormatter(); - for (String s : latexConversionStrings) { - result.add(f.format(s)); - } - return result; + return f.format(latexConversionString); } @Benchmark - public List latexToHTMLConversion() { - List result = new ArrayList<>(1000); + public String latexToHTMLConversion() { HTMLChars f = new HTMLChars(); - for (String s : latexConversionStrings) { - result.add(f.format(s)); - } - return result; + return f.format(latexConversionString); } @Benchmark - public List htmlToLatexConversion() { - List result = new ArrayList<>(1000); + public String htmlToLatexConversion() { HtmlToLatexFormatter f = new HtmlToLatexFormatter(); - for (String s : htmlConversionStrings) { - result.add(f.format(s)); - } - return result; + return f.format(htmlConversionString); } public static void main(String[] args) throws IOException, RunnerException { diff --git a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java index 56165bb7bad8..170dd1132125 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java @@ -211,38 +211,38 @@ public class HTMLUnicodeConversionMaps { /* Greek */ {"913", "Alpha", "{{$\\Alpha$}}"}, // greek capital letter alpha, U+0391 - {"914", "Beta", "{$\\Beta$}"}, // greek capital letter beta, U+0392 - {"915", "Gamma", "{$\\Gamma$}"}, // greek capital letter gamma, + {"914", "Beta", "{{$\\Beta$}}"}, // greek capital letter beta, U+0392 + {"915", "Gamma", "{{$\\Gamma$}}"}, // greek capital letter gamma, // U+0393 ISOgrk3 - {"916", "Delta", "{$\\Delta$}"}, // greek capital letter delta, + {"916", "Delta", "{{$\\Delta$}}"}, // greek capital letter delta, // U+0394 ISOgrk3 - {"917", "Epsilon", "{$\\Epsilon$}"}, // greek capital letter epsilon, U+0395 - {"918", "Zeta", "{$\\Zeta$}"}, // greek capital letter zeta, U+0396 - {"919", "Eta", "{$\\Eta$}"}, // greek capital letter eta, U+0397 - {"920", "Theta", "{$\\Theta$}"}, // greek capital letter theta, + {"917", "Epsilon", "{{$\\Epsilon$}}"}, // greek capital letter epsilon, U+0395 + {"918", "Zeta", "{{$\\Zeta$}}"}, // greek capital letter zeta, U+0396 + {"919", "Eta", "{{$\\Eta$}}"}, // greek capital letter eta, U+0397 + {"920", "Theta", "{{$\\Theta$}}"}, // greek capital letter theta, // U+0398 ISOgrk3 - {"921", "Iota", "{$\\Iota$}"}, // greek capital letter iota, U+0399 - {"922", "Kappa", "{$\\Kappa$}"}, // greek capital letter kappa, U+039A - {"923", "Lambda", "{$\\Lambda$}"}, // greek capital letter lambda, + {"921", "Iota", "{{$\\Iota$}}"}, // greek capital letter iota, U+0399 + {"922", "Kappa", "{{$\\Kappa$}}"}, // greek capital letter kappa, U+039A + {"923", "Lambda", "{{$\\Lambda$}}"}, // greek capital letter lambda, // U+039B ISOgrk3 - {"924", "Mu", "{$\\Mu$}"}, // greek capital letter mu, U+039C - {"925", "Nu", "{$\\Nu$}"}, // greek capital letter nu, U+039D - {"926", "Xi", "{$\\Xi$}"}, // greek capital letter xi, U+039E ISOgrk3 - {"927", "Omicron", "{$\\Omicron$}"}, // greek capital letter omicron, U+039F - {"928", "Pi", "{$\\Pi$}"}, // greek capital letter pi, U+03A0 ISOgrk3 - {"929", "Rho", "{$\\Rho$}"}, // greek capital letter rho, U+03A1 + {"924", "Mu", "{{$\\Mu$}}"}, // greek capital letter mu, U+039C + {"925", "Nu", "{{$\\Nu$}}"}, // greek capital letter nu, U+039D + {"926", "Xi", "{{$\\Xi$}}"}, // greek capital letter xi, U+039E ISOgrk3 + {"927", "Omicron", "{{$\\Omicron$}}"}, // greek capital letter omicron, U+039F + {"928", "Pi", "{{$\\Pi$}}"}, // greek capital letter pi, U+03A0 ISOgrk3 + {"929", "Rho", "{{$\\Rho$}}"}, // greek capital letter rho, U+03A1 /* there is no Sigmaf, and no U+03A2 character either */ - {"931", "Sigma", "{$\\Sigma$}"}, // greek capital letter sigma, + {"931", "Sigma", "{{$\\Sigma$}}"}, // greek capital letter sigma, // U+03A3 ISOgrk3 - {"932", "Tau", "{$\\Tau$}"}, // greek capital letter tau, U+03A4 - {"933", "Upsilon", "{$\\Upsilon$}"}, // greek capital letter upsilon, + {"932", "Tau", "{{$\\Tau$}}"}, // greek capital letter tau, U+03A4 + {"933", "Upsilon", "{{$\\Upsilon$}}"}, // greek capital letter upsilon, // U+03A5 ISOgrk3 - {"934", "Phi", "{$\\Phi$}"}, // greek capital letter phi, + {"934", "Phi", "{{$\\Phi$}}"}, // greek capital letter phi, // U+03A6 ISOgrk3 - {"935", "Chi", "{$\\Chi$}"}, // greek capital letter chi, U+03A7 - {"936", "Psi", "{$\\Psi$}"}, // greek capital letter psi, + {"935", "Chi", "{{$\\Chi$}}"}, // greek capital letter chi, U+03A7 + {"936", "Psi", "{{$\\Psi$}}"}, // greek capital letter psi, // U+03A8 ISOgrk3 - {"937", "Omega", "{$\\Omega$}"}, // greek capital letter omega, + {"937", "Omega", "{{$\\Omega$}}"}, // greek capital letter omega, // U+03A9 ISOgrk3 {"945", "alpha", "$\\alpha$"}, // greek small letter alpha, @@ -286,7 +286,7 @@ public class HTMLUnicodeConversionMaps { {"", "thetav", "$\\vartheta$"}, // greek small letter theta symbol, {"", "vartheta", "$\\vartheta$"}, // greek small letter theta symbol, // U+03D1 NEW - {"978", "upsih", "{$\\Upsilon$}"}, // greek upsilon with hook symbol, + {"978", "upsih", "{{$\\Upsilon$}}"}, // greek upsilon with hook symbol, // U+03D2 NEW {"982", "piv", "$\\varphi$"}, // greek pi symbol, U+03D6 ISOgrk3 @@ -306,9 +306,9 @@ public class HTMLUnicodeConversionMaps { /* Letterlike Symbols */ {"8472", "weierp", "$\\wp$"}, // script capital P = power set // = Weierstrass p, U+2118 ISOamso - {"8465", "image", "{$\\Im$}"}, // blackletter capital I = imaginary part, + {"8465", "image", "{{$\\Im$}}"}, // blackletter capital I = imaginary part, // U+2111 ISOamso - {"8476", "real", "{$\\Re$}"}, // blackletter capital R = real part symbol, + {"8476", "real", "{{$\\Re$}}"}, // blackletter capital R = real part symbol, // U+211C ISOamso {"8482", "trade", "{\\texttrademark}"}, // trade mark sign, U+2122 ISOnum {"8501", "alefsym", "$\\aleph$"}, // alef symbol = first transfinite cardinal, @@ -323,18 +323,18 @@ public class HTMLUnicodeConversionMaps { {"8596", "harr", "$\\leftrightarrow$"}, // left right arrow, U+2194 ISOamsa {"8629", "crarr", "$\\dlsh$"}, // downwards arrow with corner leftwards // = carriage return, U+21B5 NEW - require mathabx - {"8656", "lArr", "{$\\Leftarrow$}"}, // leftwards double arrow, U+21D0 ISOtech + {"8656", "lArr", "{{$\\Leftarrow$}}"}, // leftwards double arrow, U+21D0 ISOtech /* ISO 10646 does not say that lArr is the same as the 'is implied by' arrow but also does not have any other character for that function. So ? lArr can be used for 'is implied by' as ISOtech suggests */ - {"8657", "uArr", "{$\\Uparrow$}"}, // upwards double arrow, U+21D1 ISOamsa - {"8658", "rArr", "{$\\Rightarrow$}"}, // rightwards double arrow, + {"8657", "uArr", "{{$\\Uparrow$}}"}, // upwards double arrow, U+21D1 ISOamsa + {"8658", "rArr", "{{$\\Rightarrow$}}"}, // rightwards double arrow, // U+21D2 ISOtech /* ISO 10646 does not say this is the 'implies' character but does not have another character with this function so ? rArr can be used for 'implies' as ISOtech suggests */ - {"8659", "dArr", "{$\\Downarrow$}"}, // downwards double arrow, U+21D3 ISOamsa - {"8660", "hArr", "{$\\Leftrightarrow$}"}, // left right double arrow, + {"8659", "dArr", "{{$\\Downarrow$}}"}, // downwards double arrow, U+21D3 ISOamsa + {"8660", "hArr", "{{$\\Leftrightarrow$}}"}, // left right double arrow, // U+21D4 ISOamsa /* Mathematical Operators */ @@ -575,10 +575,10 @@ public class HTMLUnicodeConversionMaps { {"729", "dot", "{\\\\.{}}"}, // Dot above {"730", "ring", "{\\r{}}"}, // Ring above {"731", "ogon", "{\\k{}}"}, // Ogonek - {"733", "dblac", "{\\H{}}"}, // Double acute + {"733", "dblac", "{{\\H{}}}"}, // Double acute {"949", "epsi", "$\\epsilon$"}, // Epsilon - double check {"1013", "epsiv", "$\\varepsilonup$"}, // lunate epsilon, requires txfonts - {"1055", "", "{\\cyrchar\\CYRP}"}, // Cyrillic capital Pe + {"1055", "", "{{\\cyrchar\\CYRP}}"}, // Cyrillic capital Pe {"1082", "", "{\\cyrchar\\cyrk}"}, // Cyrillic small Ka // {"2013", "", ""}, // NKO letter FA -- Maybe en dash = 0x2013? // {"2014", "", ""}, // NKO letter FA -- Maybe em dash = 0x2014? @@ -593,17 +593,17 @@ public class HTMLUnicodeConversionMaps { {"8244", "", "{\\prime\\prime\\prime}"}, // triple prime {"8251", "", "{\\textreferencemark}"}, {"8253", "", "{\\textinterrobang}"}, {"8450", "complexes", "$\\mathbb{C}$"}, // double struck capital C -- requires e.g. amsfonts - {"8451", "", "$\\deg${C}"}, // Degree Celsius - {"8459", "Hscr", "$\\mathcal{H}$"}, // script capital H -- possibly use \mathscr - {"8460", "Hfr", "$\\mathbb{H}$"}, // black letter capital H -- requires e.g. amsfonts - {"8466", "Lscr", "$\\mathcal{L}$"}, // script capital L -- possibly use \mathscr + {"8451", "", "$\\deg${{C}}"}, // Degree Celsius + {"8459", "Hscr", "{{$\\mathcal{H}}}$"}, // script capital H -- possibly use \mathscr + {"8460", "Hfr", "{{$\\mathbb{H}$}}"}, // black letter capital H -- requires e.g. amsfonts + {"8466", "Lscr", "{{$\\mathcal{L}$}}"}, // script capital L -- possibly use \mathscr {"8467", "ell", "{\\ell}"}, // script small l - {"8469", "naturals", "$\\mathbb{N}$"}, // double struck capital N -- requires e.g. amsfonts - {"8474", "Qopf", "$\\mathbb{Q}$"}, // double struck capital Q -- requires e.g. amsfonts - {"8477", "reals", "$\\mathbb{R}$"}, // double struck capital R -- requires e.g. amsfonts - {"8486", "", "${\\Omega}$"}, // Omega + {"8469", "naturals", "{{$\\mathbb{N}$}}"}, // double struck capital N -- requires e.g. amsfonts + {"8474", "Qopf", "{{$\\mathbb{Q}$}}"}, // double struck capital Q -- requires e.g. amsfonts + {"8477", "reals", "{{$\\mathbb{R}$}}"}, // double struck capital R -- requires e.g. amsfonts + {"8486", "", "${{\\Omega}}$"}, // Omega {"8491", "angst", "{{\\AA}}"}, // Angstrom - {"8496", "Escr", "$\\mathcal{E}$"}, // script capital E + {"8496", "Escr", "{{$\\mathcal{E}$}}"}, // script capital E {"8531", "frac13", "$\\sfrac{1}{3}$"}, // Vulgar fraction one third {"8532", "frac23", "$\\sfrac{2}{3}$"}, // Vulgar fraction two thirds {"8533", "frac15", "$\\sfrac{1}{5}$"}, // Vulgar fraction one fifth diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index 37578d146168..12529c4836dc 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -263,7 +263,7 @@ public void cleanupHtmlToLatexConvertsEpsilonToLatex() { entry.setField("title", "Ε"); worker.cleanup(preset, entry); - Assert.assertEquals("{$\\Epsilon$}", entry.getField("title")); + Assert.assertEquals("{{$\\Epsilon$}}", entry.getField("title")); } @Test diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java index 3db99a42d85a..75785edb2365 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java @@ -45,7 +45,7 @@ public void testHTML() { assertEquals("{\\\"{a}}", formatter.format("ä")); assertEquals("{\\\"{a}}", formatter.format("ä")); assertEquals("{\\\"{a}}", formatter.format("ä")); - assertEquals("{$\\Epsilon$}", formatter.format("Ε")); + assertEquals("{{$\\Epsilon$}}", formatter.format("Ε")); } @Test diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java index 9a222b6bbe66..4d14e4aa2895 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java @@ -35,7 +35,7 @@ public void testUnicodeCombiningAccents() { @Test public void testUnicode() { assertEquals("{\\\"{a}}", formatter.format("ä")); - assertEquals("{$\\Epsilon$}", formatter.format("\u0395")); + assertEquals("{{$\\Epsilon$}}", formatter.format("\u0395")); } @Test From a4dcc6106fa8f7c6b3bb04c2ae664aea8e88f4b9 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 21 Apr 2016 21:23:34 +0200 Subject: [PATCH 120/268] Added two characters --- .../sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java index 170dd1132125..93695cfa27ea 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java @@ -551,6 +551,8 @@ public class HTMLUnicodeConversionMaps { {"339", "", "{{\\oe}}"}, // oe-ligature {"348", "Scirc", "{{\\^{S}}}"}, // upper case S with circumflex {"349", "scirc", "{\\^{s}}"}, // lower case s with circumflex + {"350", "Scedil", "{{\\c{S}}}"}, // upper case S with cedilla + {"351", "scedil", "{\\c{s}}"}, // lower case s with cedilla {"370", "Uogon", "{{\\k{U}}}"}, // capital U with ogonek {"371", "uogon", "{\\k{u}}"}, // small u with ogonek {"381", "Zcaron", "{{\\v{Z}}}"}, // capital Z with caron From 2d04b6c5bf1fd582a57e5e67a9f6c4cc7ca37228 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 2 Jun 2016 21:11:24 +0200 Subject: [PATCH 121/268] Update AUTHORS --- .mailmap | 3 +++ AUTHORS | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.mailmap b/.mailmap index f91b578b66f9..00050a12e8f8 100644 --- a/.mailmap +++ b/.mailmap @@ -14,6 +14,7 @@ Nicolas Pavillon Koji Yokota kojiyokota Koji Yokota Koji Yokota +Koji Yokota Dominik Waßenhoven Thomas Arildsen ThomasArildsen @@ -33,6 +34,7 @@ Michael Falkenthal Michael Falkenthal Eduardo Greco +Daniel Bruehl Egon Willighagen Frédéric Darboux Frédéric Darboux @@ -82,6 +84,7 @@ Ulrik Stervbo Stefano Gariazzo Lee Patton Jörg Lenhard +Jörg Lenhard diff --git a/AUTHORS b/AUTHORS index e87437808f1e..e3b803ffe0de 100644 --- a/AUTHORS +++ b/AUTHORS @@ -29,6 +29,7 @@ Christopher Oezbek Christopher S. Lester Cyrille d'Haese Dale Visser +Daniel Bruehl Daniel Mair Daniel Svärd David Gleich @@ -136,6 +137,7 @@ Samin Muhammad Ridwanul Karim Sascha Hunold Sascha Zeller Saverio Mori +Scott Townsend Seb Wills Siedlerchr Simon Harrer From e390d197ee4d7e5cfd08bd03ef467c1b29b6309f Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 2 Jun 2016 21:13:16 +0200 Subject: [PATCH 122/268] Release v3.4 --- CHANGELOG.md | 17 ++--------------- README.md | 4 +--- build.gradle | 4 ++-- jabref.install4j | 6 +++--- scripts/prepare-install4j.sh | 6 +++--- 5 files changed, 11 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b75d8828dc9b..fded9fdac744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Here, the categories "Changed" for added and changed functionality, We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#NUM`. -## [Unreleased] +## [3.4] - 2016-06-02 ### Changed - Implemented [#629](https://github.com/JabRef/jabref/issues/629): Explicit groups are now written in the "groups" field of the entry instead of at the end of the bib file @@ -73,19 +73,6 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Removed not-working option "Select Matches" under Groups -> Settings. - - - - - - - - - - - - - ## [3.3] - 2016-04-17 ### Changed @@ -380,7 +367,7 @@ Since much functionality has changed during development, a release of this versi The changelog of 2.11 and versions before is maintained as [text file](https://github.com/JabRef/jabref/blob/dev_2.11/CHANGELOG) in the [dev_2.11 branch](https://github.com/JabRef/jabref/tree/dev_2.11). -[Unreleased]: https://github.com/JabRef/jabref/compare/v3.3...HEAD +[3.4]: https://github.com/JabRef/jabref/compare/v3.3...v3.4 [3.3]: https://github.com/JabRef/jabref/compare/v3.2...v3.3 [3.2]: https://github.com/JabRef/jabref/compare/v3.1...v3.2 [3.1]: https://github.com/JabRef/jabref/compare/v3.0...v3.1 diff --git a/README.md b/README.md index 81856cd0ae8a..05c44c4bbf54 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# JabRef Development Version +# JabRef Version 3.4 [![Build Status](https://travis-ci.org/JabRef/jabref.svg?branch=master)](https://travis-ci.org/JabRef/jabref) [![Dependency Status](https://www.versioneye.com/user/projects/557f2723386664002000009c/badge.svg?style=flat)](https://www.versioneye.com/user/projects/557f2723386664002000009c) @@ -8,8 +8,6 @@ [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/issue)](http://www.issuestats.com/github/jabref/jabref) [![Codacy Badge](https://api.codacy.com/project/badge/grade/327430c894e04086a5bfef618fa44f36)](https://www.codacy.com/app/simonharrer/jabref) -This version is a development version. Features may not work as expected. - Branches of JabRef development are listed at https://github.com/JabRef/jabref/wiki/Branches. Development builds are available at [builds.jabref.org](http://builds.jabref.org/master/), the [latest release is available via GitHub](https://github.com/JabRef/jabref/releases/latest). diff --git a/build.gradle b/build.gradle index 6d7558a6952c..ac5eb794d396 100644 --- a/build.gradle +++ b/build.gradle @@ -34,8 +34,8 @@ apply from: 'eclipse.gradle' apply from: 'localization.gradle' group = "net.sf.jabref" -version = "3.4dev" -project.ext.threeDotVersion = "3.3.0.1" +version = "3.4" +project.ext.threeDotVersion = "3.4.0.0" project.ext.install4jDir = hasProperty("install4jDir") ? getProperty("install4jDir") : (OperatingSystem.current().isWindows() ? 'C:/Program Files/install4j6' : 'install4j6') sourceCompatibility = 1.8 targetCompatibility = 1.8 diff --git a/jabref.install4j b/jabref.install4j index c8284af3a30d..d1bc2f25767a 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -646,7 +646,7 @@ return true; - + @@ -659,7 +659,7 @@ return true; - + @@ -672,7 +672,7 @@ return true; - + diff --git a/scripts/prepare-install4j.sh b/scripts/prepare-install4j.sh index 9f448164cdb6..354ee9df46fb 100755 --- a/scripts/prepare-install4j.sh +++ b/scripts/prepare-install4j.sh @@ -20,6 +20,6 @@ if [ ! -d ~/.install4j6/jres/ ]; then mkdir -p ~/.install4j6/jres/ fi cd ~/.install4j6/jres/ -wget --quiet -nc http://files.jabref.org/jres/windows-x86-1.8.0_77.tar.gz -wget --quiet -nc http://files.jabref.org/jres/windows-amd64-1.8.0_77.tar.gz -wget --quiet -nc http://files.jabref.org/jres/macosx-amd64-1.8.0_77_unpacked.tar.gz +wget --quiet -nc http://files.jabref.org/jres/windows-x86-1.8.0_92.tar.gz +wget --quiet -nc http://files.jabref.org/jres/windows-amd64-1.8.0_92.tar.gz +wget --quiet -nc http://files.jabref.org/jres/macosx-amd64-1.8.0_92_unpacked.tar.gz From f092a857ffee879d163ab4a2815d1239f21e0635 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 2 Jun 2016 21:31:33 +0200 Subject: [PATCH 123/268] Build release --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 994b47d7e822..3d64fb9a7492 100644 --- a/circle.yml +++ b/circle.yml @@ -17,7 +17,7 @@ dependencies: test: override: - - ./gradlew -Pdev=true -Pinstall4jDir="install4j6" release --stacktrace + - ./gradlew -Pdev=false -Pinstall4jDir="install4j6" release --stacktrace deployment: release: From d18988e18263d3657efcf55a1a8551b4585ea237 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 2 Jun 2016 21:40:22 +0200 Subject: [PATCH 124/268] Revert script change --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 3d64fb9a7492..994b47d7e822 100644 --- a/circle.yml +++ b/circle.yml @@ -17,7 +17,7 @@ dependencies: test: override: - - ./gradlew -Pdev=false -Pinstall4jDir="install4j6" release --stacktrace + - ./gradlew -Pdev=true -Pinstall4jDir="install4j6" release --stacktrace deployment: release: From 8e3484ac7999fba3d89bed9f5310543c218e2dde Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 2 Jun 2016 21:45:17 +0200 Subject: [PATCH 125/268] Show development information --- CHANGELOG.md | 10 ++++++++++ README.md | 4 +++- build.gradle | 4 ++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fded9fdac744..327d3bc5cb75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,15 @@ Here, the categories "Changed" for added and changed functionality, We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#NUM`. +## [Unreleased] + +### Changed + +### Fixed + +### Removed + + ## [3.4] - 2016-06-02 ### Changed @@ -367,6 +376,7 @@ Since much functionality has changed during development, a release of this versi The changelog of 2.11 and versions before is maintained as [text file](https://github.com/JabRef/jabref/blob/dev_2.11/CHANGELOG) in the [dev_2.11 branch](https://github.com/JabRef/jabref/tree/dev_2.11). +[Unreleased]: https://github.com/JabRef/jabref/compare/v3.4...HEAD [3.4]: https://github.com/JabRef/jabref/compare/v3.3...v3.4 [3.3]: https://github.com/JabRef/jabref/compare/v3.2...v3.3 [3.2]: https://github.com/JabRef/jabref/compare/v3.1...v3.2 diff --git a/README.md b/README.md index 05c44c4bbf54..81856cd0ae8a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# JabRef Version 3.4 +# JabRef Development Version [![Build Status](https://travis-ci.org/JabRef/jabref.svg?branch=master)](https://travis-ci.org/JabRef/jabref) [![Dependency Status](https://www.versioneye.com/user/projects/557f2723386664002000009c/badge.svg?style=flat)](https://www.versioneye.com/user/projects/557f2723386664002000009c) @@ -8,6 +8,8 @@ [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/issue)](http://www.issuestats.com/github/jabref/jabref) [![Codacy Badge](https://api.codacy.com/project/badge/grade/327430c894e04086a5bfef618fa44f36)](https://www.codacy.com/app/simonharrer/jabref) +This version is a development version. Features may not work as expected. + Branches of JabRef development are listed at https://github.com/JabRef/jabref/wiki/Branches. Development builds are available at [builds.jabref.org](http://builds.jabref.org/master/), the [latest release is available via GitHub](https://github.com/JabRef/jabref/releases/latest). diff --git a/build.gradle b/build.gradle index ac5eb794d396..27858aa0947f 100644 --- a/build.gradle +++ b/build.gradle @@ -34,8 +34,8 @@ apply from: 'eclipse.gradle' apply from: 'localization.gradle' group = "net.sf.jabref" -version = "3.4" -project.ext.threeDotVersion = "3.4.0.0" +version = "3.5dev" +project.ext.threeDotVersion = "3.4.0.1" project.ext.install4jDir = hasProperty("install4jDir") ? getProperty("install4jDir") : (OperatingSystem.current().isWindows() ? 'C:/Program Files/install4j6' : 'install4j6') sourceCompatibility = 1.8 targetCompatibility = 1.8 From 9388be722cc5e54d0b4d5d883197be87d5710bbe Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 3 Jun 2016 11:39:56 +0200 Subject: [PATCH 126/268] Update CHANGELOG.md Add empty lines to cause merge conflicts for PRs not being merged before release of v3.4 --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 327d3bc5cb75..8139f01fce60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,35 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Removed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## [3.4] - 2016-06-02 ### Changed From 28bfea0b6ba66359f30b0b6b8c75f467baba81b9 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Fri, 3 Jun 2016 11:49:15 +0200 Subject: [PATCH 127/268] Fix changelog --- CHANGELOG.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 542606c2d3b5..270a522dc4fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Changed ### Fixed +- Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them +- Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file + ### Removed @@ -101,7 +104,6 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1457](https://github.com/JabRef/jabref/issues/1457): Support multiple words inside LaTeX commands to RTF export - Entries retain their groupmembership when undoing their cut/deletion - Fixed [#1450](https://github.com/JabRef/jabref/issues/1450): EntryEditor is restored in the correct size after preference changes -- Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic @@ -163,10 +165,6 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - [#969](https://github.com/JabRef/jabref/issues/969) Adding and replacing old event system mechanisms with Google Guava EventBus. ### Fixed -<<<<<<< 973a39d9fa61ad9149db778e27112ecaeb13d712 -- Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file -======= ->>>>>>> Added double {} around all symbols with capital letters to avoid lowercasing in titles. Fixed #405 - Fixed [#318](https://github.com/JabRef/jabref/issues/318): Improve normalization of author names - Fixed [#598](https://github.com/JabRef/jabref/issues/598) and [#402](https://github.com/JabRef/jabref/issues/402): No more issues with invalid icons for ExternalFileTypes in global search or after editing the settings - Fixed [#883](https://github.com/JabRef/jabref/issues/883): No NPE during cleanup From 43301dcb3a588bbb45cfa9c72ae07460a83b4e33 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 3 Jun 2016 11:54:35 +0200 Subject: [PATCH 128/268] Fixes (#1231) * Removed _ from FontSelectorDialog --- .../net/sf/jabref/benchmarks/Benchmarks.java | 3 +- .../jabref/gui/DuplicateResolverDialog.java | 8 +-- .../net/sf/jabref/gui/DuplicateSearch.java | 4 +- .../sf/jabref/gui/ImportInspectionDialog.java | 8 +-- .../sf/jabref/gui/ReplaceStringDialog.java | 72 +++++++------------ .../java/net/sf/jabref/gui/StringDialog.java | 2 +- .../gui/preftabs/FontSelectorDialog.java | 14 ++-- .../gui/preftabs/LabelPatternPrefTab.java | 18 +++-- src/main/resources/l10n/JabRef_da.properties | 10 +-- src/main/resources/l10n/JabRef_de.properties | 10 +-- src/main/resources/l10n/JabRef_en.properties | 10 +-- src/main/resources/l10n/JabRef_es.properties | 10 +-- src/main/resources/l10n/JabRef_fa.properties | 10 +-- src/main/resources/l10n/JabRef_fr.properties | 10 +-- src/main/resources/l10n/JabRef_in.properties | 10 +-- src/main/resources/l10n/JabRef_it.properties | 10 +-- src/main/resources/l10n/JabRef_ja.properties | 10 +-- src/main/resources/l10n/JabRef_nl.properties | 10 +-- src/main/resources/l10n/JabRef_no.properties | 10 +-- .../resources/l10n/JabRef_pt_BR.properties | 10 +-- src/main/resources/l10n/JabRef_ru.properties | 10 +-- src/main/resources/l10n/JabRef_sv.properties | 10 +-- src/main/resources/l10n/JabRef_tr.properties | 10 +-- src/main/resources/l10n/JabRef_vi.properties | 10 +-- src/main/resources/l10n/JabRef_zh.properties | 10 +-- src/test/java/net/sf/jabref/MetaDataTest.java | 3 +- 26 files changed, 140 insertions(+), 162 deletions(-) diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index bfd53437312e..3c91bfea5548 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -14,7 +14,6 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.exporter.BibDatabaseWriter; -import net.sf.jabref.exporter.SaveException; import net.sf.jabref.exporter.SavePreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -43,7 +42,7 @@ public class Benchmarks { private String htmlConversionString; @Setup - public void init() throws IOException, SaveException { + public void init() throws IOException { Globals.prefs = JabRefPreferences.getInstance(); Random randomizer = new Random(); diff --git a/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java b/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java index 03efbc1d5490..ae17efc1af91 100644 --- a/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java +++ b/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java @@ -45,8 +45,8 @@ enum DuplicateResolverType { enum DuplicateResolverResult { NOT_CHOSEN, KEEP_BOTH, - KEEP_UPPER, - KEEP_LOWER, + KEEP_LEFT, + KEEP_RIGHT, AUTOREMOVE_EXACT, KEEP_MERGE, BREAK @@ -117,8 +117,8 @@ private void init(BibEntry one, BibEntry two, DuplicateResolverType type) { options.add(Box.createHorizontalStrut(5)); options.add(cancel); - first.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_UPPER)); - second.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_LOWER)); + first.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_LEFT)); + second.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_RIGHT)); both.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_BOTH)); merge.addActionListener(e -> buttonPressed(DuplicateResolverResult.KEEP_MERGE)); if (removeExact != null) { diff --git a/src/main/java/net/sf/jabref/gui/DuplicateSearch.java b/src/main/java/net/sf/jabref/gui/DuplicateSearch.java index 218b1ea1858e..06f8786bd015 100644 --- a/src/main/java/net/sf/jabref/gui/DuplicateSearch.java +++ b/src/main/java/net/sf/jabref/gui/DuplicateSearch.java @@ -105,13 +105,13 @@ public void run() { duplicateCounter++; DuplicateResolverResult answer = cb.getSelected(); - if ((answer == DuplicateResolverResult.KEEP_UPPER) + if ((answer == DuplicateResolverResult.KEEP_LEFT) || (answer == DuplicateResolverResult.AUTOREMOVE_EXACT)) { toRemove.add(be[1]); if (answer == DuplicateResolverResult.AUTOREMOVE_EXACT) { autoRemoveExactDuplicates = true; // Remember choice } - } else if (answer == DuplicateResolverResult.KEEP_LOWER) { + } else if (answer == DuplicateResolverResult.KEEP_RIGHT) { toRemove.add(be[0]); } else if (answer == DuplicateResolverResult.BREAK) { st.setFinished(); // thread killing diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 7f27f3b475de..2e6ccbae29fb 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -1034,7 +1034,7 @@ public void mousePressed(MouseEvent e) { diag.setLocationRelativeTo(ImportInspectionDialog.this); diag.setVisible(true); ImportInspectionDialog.this.toFront(); - if (diag.getSelected() == DuplicateResolverResult.KEEP_UPPER) { + if (diag.getSelected() == DuplicateResolverResult.KEEP_LEFT) { // Remove old entry. Or... add it to a list of entries // to be deleted. We only delete // it after Ok is clicked. @@ -1050,7 +1050,7 @@ public void mousePressed(MouseEvent e) { entries.getReadWriteLock().writeLock().unlock(); } - } else if (diag.getSelected() == DuplicateResolverResult.KEEP_LOWER) { + } else if (diag.getSelected() == DuplicateResolverResult.KEEP_RIGHT) { // Remove the entry from the import inspection dialog. entries.getReadWriteLock().writeLock().lock(); try { @@ -1096,10 +1096,10 @@ public void mousePressed(MouseEvent e) { diag.setVisible(true); ImportInspectionDialog.this.toFront(); DuplicateResolverResult answer = diag.getSelected(); - if (answer == DuplicateResolverResult.KEEP_UPPER) { + if (answer == DuplicateResolverResult.KEEP_LEFT) { entries.remove(other.get()); first.setGroupHit(false); - } else if (answer == DuplicateResolverResult.KEEP_LOWER) { + } else if (answer == DuplicateResolverResult.KEEP_RIGHT) { entries.remove(first); } else if (answer == DuplicateResolverResult.KEEP_BOTH) { first.setGroupHit(false); diff --git a/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java b/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java index 3d78af6c2ac9..182d7c902f87 100644 --- a/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java +++ b/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java @@ -44,22 +44,21 @@ import net.sf.jabref.model.entry.BibEntry; /** - * Dialog for creating or modifying groups. Operates directly on the - * Vector containing group information. + * Dialog for replacing strings. */ class ReplaceStringDialog extends JDialog { - private final JTextField fields = new JTextField("", 30); - private final JTextField from = new JTextField("", 30); - private final JTextField to = new JTextField("", 30); + private final JTextField fieldsField = new JTextField("", 30); + private final JTextField fromField = new JTextField("", 30); + private final JTextField toField = new JTextField("", 30); private final JCheckBox selOnly = new JCheckBox(Localization.lang("Limit to selected entries"), false); private final JRadioButton allFi = new JRadioButton(Localization.lang("All fields"), true); private final JRadioButton field = new JRadioButton(Localization.lang("Limit to fields") + ":", false); private boolean okPressed; - private String[] flds; - private String s1; - private String s2; + private String[] fieldStrings; + private String fromString; + private String toString; public ReplaceStringDialog(JabRefFrame parent) { @@ -68,24 +67,20 @@ public ReplaceStringDialog(JabRefFrame parent) { ButtonGroup bg = new ButtonGroup(); bg.add(allFi); bg.add(field); - ActionListener okListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - s1 = from.getText(); - s2 = to.getText(); - if ("".equals(s1)) { - return; - } - okPressed = true; - flds = fields.getText().toLowerCase().split(";"); - dispose(); + ActionListener okListener = e -> { + fromString = fromField.getText(); + toString = toField.getText(); + if ("".equals(fromString)) { + return; } + okPressed = true; + fieldStrings = fieldsField.getText().toLowerCase().split(";"); + dispose(); }; JButton ok = new JButton(Localization.lang("OK")); ok.addActionListener(okListener); - to.addActionListener(okListener); - fields.addActionListener(okListener); + toField.addActionListener(okListener); + fieldsField.addActionListener(okListener); AbstractAction cancelAction = new AbstractAction() { @Override @@ -119,19 +114,8 @@ public void actionPerformed(ActionEvent e) { Localization.lang("Strings"))); // Settings panel: - /* - con.weightx = 0; - con.insets = new Insets(3, 5, 3, 5); - con.anchor = GridBagConstraints.EAST; - con.fill = GridBagConstraints.NONE; - con.gridx = 0; - con.gridy = 2; - gbl.setConstraints(nf, con); - settings.add(nf);*/ - //con.weightx = 1; GridBagConstraints con = new GridBagConstraints(); con.fill = GridBagConstraints.HORIZONTAL; - //JSeparator sep = new JSeparator() con.gridwidth = 2; con.weightx = 0; con.anchor = GridBagConstraints.WEST; @@ -152,9 +136,8 @@ public void actionPerformed(ActionEvent e) { settings.add(field); con.gridx = 1; con.weightx = 1; - //con.insets = new Insets(3, 5, 3, 5); - gbl.setConstraints(fields, con); - settings.add(fields); + gbl.setConstraints(fieldsField, con); + settings.add(fieldsField); con.weightx = 0; con.gridx = 0; @@ -169,11 +152,11 @@ public void actionPerformed(ActionEvent e) { con.weightx = 1; con.gridx = 1; con.gridy = 0; - gbl.setConstraints(from, con); - main.add(from); + gbl.setConstraints(fromField, con); + main.add(fromField); con.gridy = 1; - gbl.setConstraints(to, con); - main.add(to); + gbl.setConstraints(toField, con); + main.add(toField); // Option buttons: con.gridx = GridBagConstraints.RELATIVE; @@ -194,7 +177,6 @@ public void actionPerformed(ActionEvent e) { getContentPane().add(opt, BorderLayout.SOUTH); pack(); - //setSize(400, 170); this.setLocationRelativeTo(parent); } @@ -226,7 +208,7 @@ public int replace(BibEntry be, NamedCompound ce) { } } } else { - for (String fld : flds) { + for (String fld : fieldStrings) { if (!fld.equals(BibEntry.KEY_FIELD)) { counter += replaceField(be, fld, ce); } @@ -245,11 +227,11 @@ private int replaceField(BibEntry be, String fieldname, NamedCompound ce) { int ind; int piv = 0; int counter = 0; - int len1 = s1.length(); - while ((ind = txt.indexOf(s1, piv)) >= 0) { + int len1 = fromString.length(); + while ((ind = txt.indexOf(fromString, piv)) >= 0) { counter++; sb.append(txt.substring(piv, ind)); // Text leading up to s1 - sb.append(s2); // Insert s2 + sb.append(toString); // Insert s2 piv = ind + len1; } sb.append(txt.substring(piv)); diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index beac57e5a8c2..6d8fcf1159ca 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -78,7 +78,7 @@ class StringDialog extends JDialog { // The action concerned with closing the window. private final CloseAction closeAction = new CloseAction(); - public static final String STRINGS_TITLE = Localization.lang("Strings for database"); + private static final String STRINGS_TITLE = Localization.lang("Strings for database"); public StringDialog(JabRefFrame frame, BasePanel panel, BibDatabase base) { diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FontSelectorDialog.java b/src/main/java/net/sf/jabref/gui/preftabs/FontSelectorDialog.java index b943fbc20dd5..78cdc32f01b7 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FontSelectorDialog.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FontSelectorDialog.java @@ -101,7 +101,7 @@ Portions copyright (C) 1999 Jason Ginchereau * Added more translations, and started work on a Replace string feature * * Revision 1.4 2004/02/17 09:14:02 mortenalver - * Similar update in FontSelector preview. + * Similar update in Font selection preview. * * Revision 1.3 2004/02/17 07:35:22 mortenalver * Experimenting with antialiasing in table. @@ -158,7 +158,7 @@ public class FontSelectorDialog extends JDialog { public FontSelectorDialog(Component comp, Font font) { - super(JOptionPane.getFrameForComponent(comp), Localization.lang("FontSelector"), true); // + super(JOptionPane.getFrameForComponent(comp), Localization.lang("Font selection"), true); // JPanel content = new JPanel(new BorderLayout()); content.setBorder(new EmptyBorder(12, 12, 12, 12)); setContentPane(content); @@ -167,13 +167,13 @@ public FontSelectorDialog(Component comp, Font font) { familyList = new JList<>(getFontList()); - JPanel familyPanel = createTextFieldAndListPanel(Localization.lang("Font Family"), familyField, familyList); + JPanel familyPanel = createTextFieldAndListPanel(Localization.lang("Font family"), familyField, familyList); listPanel.add(familyPanel); - JPanel sizePanel = createTextFieldAndListPanel(Localization.lang("Font Size"), sizeField, sizeList); + JPanel sizePanel = createTextFieldAndListPanel(Localization.lang("Font size"), sizeField, sizeList); listPanel.add(sizePanel); - JPanel stylePanel = createTextFieldAndListPanel(Localization.lang("Font Style"), styleField, styleList); + JPanel stylePanel = createTextFieldAndListPanel(Localization.lang("Font style"), styleField, styleList); styleField.setEditable(false); listPanel.add(stylePanel); @@ -196,7 +196,7 @@ public FontSelectorDialog(Component comp, Font font) { | enable antialiasing in the preview field, since I'm | | working on introducing this in the table view. | -------------------------------------------------------- */ - preview = new JLabel(Localization.lang("Font Preview")) { + preview = new JLabel(Localization.lang("Font preview")) { @Override public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; @@ -208,7 +208,7 @@ public void paint(Graphics g) { }; - preview.setBorder(new TitledBorder(Localization.lang("Font Preview"))); + preview.setBorder(new TitledBorder(Localization.lang("Font preview"))); updatePreview(); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java b/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java index 445bf61eed2e..0aa5347ec6da 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java @@ -51,8 +51,8 @@ class LabelPatternPrefTab extends LabelPatternPanel implements PrefsTab { private final JRadioButton letterStartB = new JRadioButton(Localization.lang("Ensure unique keys using letters (b, c, ...)")); private final JRadioButton alwaysAddLetter = new JRadioButton(Localization.lang("Always add letter (a, b, ...) to generated keys")); - private final JTextField KeyPatternRegex = new JTextField(20); - private final JTextField KeyPatternReplacement = new JTextField(20); + private final JTextField keyPatternRegex = new JTextField(20); + private final JTextField keyPatternReplacement = new JTextField(20); public LabelPatternPrefTab(JabRefPreferences prefs, BasePanel panel) { @@ -74,8 +74,8 @@ public void storeSettings() { Globals.prefs.putBoolean(JabRefPreferences.WARN_BEFORE_OVERWRITING_KEY, warnBeforeOverwriting.isSelected()); Globals.prefs.putBoolean(JabRefPreferences.AVOID_OVERWRITING_KEY, dontOverwrite.isSelected()); - Globals.prefs.put(JabRefPreferences.KEY_PATTERN_REGEX, KeyPatternRegex.getText()); - Globals.prefs.put(JabRefPreferences.KEY_PATTERN_REPLACEMENT, KeyPatternReplacement.getText()); + Globals.prefs.put(JabRefPreferences.KEY_PATTERN_REGEX, keyPatternRegex.getText()); + Globals.prefs.put(JabRefPreferences.KEY_PATTERN_REPLACEMENT, keyPatternReplacement.getText()); Globals.prefs.putBoolean(JabRefPreferences.GENERATE_KEYS_AFTER_INSPECTION, autoGenerateOnImport.isSelected()); Globals.prefs.putBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING, generateOnSave.isSelected()); @@ -133,8 +133,8 @@ private void appendKeyGeneratorSettings() { builder.nextLine(); builder.append(pan); - builder.append(KeyPatternRegex); - builder.append(KeyPatternReplacement); + builder.append(keyPatternRegex); + builder.append(keyPatternReplacement); builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); con.gridx = 1; @@ -177,11 +177,9 @@ public void setValues() { // Warning before overwriting is only relevant if overwriting can happen: warnBeforeOverwriting.setEnabled(!dontOverwrite.isSelected()); - KeyPatternRegex.setText(Globals.prefs.get(JabRefPreferences.KEY_PATTERN_REGEX)); - KeyPatternReplacement.setText(Globals.prefs.get(JabRefPreferences.KEY_PATTERN_REPLACEMENT)); + keyPatternRegex.setText(Globals.prefs.get(JabRefPreferences.KEY_PATTERN_REGEX)); + keyPatternReplacement.setText(Globals.prefs.get(JabRefPreferences.KEY_PATTERN_REPLACEMENT)); - //basenamePatternRegex.setText(Globals.prefs.get("basenamePatternRegex")); - //basenamePatternReplacement.setText(Globals.prefs.get("basenamePatternReplacement")); } @Override diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 585e1370651e..550158bcbb77 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -337,11 +337,11 @@ First_select_the_entries_you_want_keys_to_be_generated_for.=Vælg_først_hvilke_ Fit_table_horizontally_on_screen=Tilpas_tabelbredden_horisontalt Float=Flyt Float_marked_entries=Sorter_mærkede_poster_øverst -Font_Family=Skrifttype-familie -Font_Preview=Skrifttype-forhåndsvisning -Font_Size=Skriftstørrelse -Font_Style=Skrifttype-stil -FontSelector=Skrifttypevælger +Font_family=Skrifttype-familie +Font_preview=Skrifttype-forhåndsvisning +Font_size=Skriftstørrelse +Font_style=Skrifttype-stil +Font_selection=Skrifttypevælger for=for Format_of_author_and_editor_names=Formattering_af_forfatter-_og_redaktørnavn Format_String=Formatstreng diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index fcc8d6687599..f04e9a7e8a14 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -608,15 +608,15 @@ Float=Oben_einsortieren Float_marked_entries=Markierte_Einträge_zuoberst_anzeigen -Font_Family=Schriftart +Font_family=Schriftart -Font_Preview=Vorschau +Font_preview=Vorschau -Font_Size=Schriftgröße +Font_size=Schriftgröße -Font_Style=Schriftstil +Font_style=Schriftstil -FontSelector=Schriften_wählen +Font_selection=Schriften_wählen for=für diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index babd36026bf9..e887828d629d 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -582,15 +582,15 @@ Fit_table_horizontally_on_screen=Fit_table_horizontally_on_screen Float=Float Float_marked_entries=Float_marked_entries -Font_Family=Font_Family +Font_family=Font_family -Font_Preview=Font_Preview +Font_preview=Font_preview -Font_Size=Font_Size +Font_size=Font_size -Font_Style=Font_Style +Font_style=Font_style -FontSelector=FontSelector +Font_selection=Font_selection for=for diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index c1c4f1a436ac..2fb5b39ecb60 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -313,11 +313,11 @@ First_select_the_entries_you_want_keys_to_be_generated_for.=En_primer_lugar,_sel Fit_table_horizontally_on_screen=Ajustar_la_tabla_al_ancho_de_pantalla Float=Flotar Float_marked_entries=Flotar_entradas_marcadas -Font_Family=Tipo_de_letra -Font_Preview=Vista_previa_del_tipo_de_letra -Font_Size=Tamaño_de_tipo_de_letra -Font_Style=Estilo_de_tipo_de_letra -FontSelector=Selector_tipo_de_letra +Font_family=Tipo_de_letra +Font_preview=Vista_previa_del_tipo_de_letra +Font_size=Tamaño_de_tipo_de_letra +Font_style=Estilo_de_tipo_de_letra +Font_selection=Selector_tipo_de_letra for=para Format_of_author_and_editor_names=Formato_de_los_nombres_de_autor_y_editor Format_String=Formatear_cadena diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 7f8c32fc98e0..b2bbeafdef4f 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -593,15 +593,15 @@ Fit_table_horizontally_on_screen= Float= Float_marked_entries= -Font_Family= +Font_family= -Font_Preview= +Font_preview= -Font_Size= +Font_size= -Font_Style= +Font_style= -FontSelector= +Font_selection= for= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 9b042d726853..56fc60bc4e71 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -313,11 +313,11 @@ First_select_the_entries_you_want_keys_to_be_generated_for.=Commencez_par_sélec Fit_table_horizontally_on_screen=Ajuster_horizontalement_la_table_à_l'écran Float=Flottante Float_marked_entries=Entrées_marquées_flottantes -Font_Family=Famille_de_police -Font_Preview=Prévisualisation_de_la_police -Font_Size=Taille_de_police -Font_Style=Style_de_police -FontSelector=Sélecteur_de_police +Font_family=Famille_de_police +Font_preview=Prévisualisation_de_la_police +Font_size=Taille_de_police +Font_style=Style_de_police +Font_selection=Sélecteur_de_police for=pour Format_of_author_and_editor_names=Format_des_noms_d'auteurs_et_d'éditeurs Format_String=Chaîne_de_format diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 9c6b815b6e89..89b0904f65ca 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -313,11 +313,11 @@ First_select_the_entries_you_want_keys_to_be_generated_for.=Pertama_pilih_entri_ Fit_table_horizontally_on_screen=Sesuaikan_ukuran_tabel_horisontal_sesuai_layar Float=Ambangan Float_marked_entries=Ambangan_ditandai_sebagai_entri -Font_Family=Keluarga_Huruf -Font_Preview=Pratampilan_Huruf -Font_Size=Ukuran_Huruf -Font_Style=Corak_huruf -FontSelector=PemilihHuruf +Font_family=Keluarga_Huruf +Font_preview=Pratampilan_Huruf +Font_size=Ukuran_Huruf +Font_style=Corak_huruf +Font_selection=PemilihHuruf for=untuk Format_of_author_and_editor_names=Format_nama_penulis_dan_penyunting Format_String=Format_String diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 39a340b50f7f..8c33ecf77b97 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -338,11 +338,11 @@ First_select_the_entries_you_want_keys_to_be_generated_for.=Selezionare_dapprima Fit_table_horizontally_on_screen=Adatta_la_tabella_allo_schermo_orizontalmente Float=Galleggiante Float_marked_entries=Voci_evidenziate_sempre_in_alto -Font_Family=Famiglia_di_font -Font_Preview=Anteprima_font -Font_Size=Dimensione_font -Font_Style=Stile_font -FontSelector=Selettore_dei_font +Font_family=Famiglia_di_font +Font_preview=Anteprima_font +Font_size=Dimensione_font +Font_style=Stile_font +Font_selection=Selettore_dei_font for=per Format_of_author_and_editor_names=Formato_dei_nomi_di_autori_e_curatori Format_String=Stringa_di_formattazione diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index ca4dd9cd0c1a..d7ad6051f83b 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -594,15 +594,15 @@ Fit_table_horizontally_on_screen=表を画面上の水平方向に合わせて Float=上部に表示 Float_marked_entries=標識を付けた項目を上部へ -Font_Family=フォント族 +Font_family=フォント族 -Font_Preview=フォントプレビュー +Font_preview=フォントプレビュー -Font_Size=フォント寸法 +Font_size=フォント寸法 -Font_Style=フォント様式 +Font_style=フォント様式 -FontSelector=フォントの選択 +Font_selection=フォントの選択 for=;_対象\: diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index afed41b4612c..4a818cc7ac42 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -611,15 +611,15 @@ Float=Float Float_marked_entries=Gemarkeerde_entries_bovenaan_tonen -Font_Family=Lettertype_Type +Font_family=Lettertype_Type -Font_Preview=Lettertype_Voorbeeld +Font_preview=Lettertype_Voorbeeld -Font_Size=Lettertype_Grootte +Font_size=Lettertype_Grootte -Font_Style=Lettertype_Stijl +Font_style=Lettertype_Stijl -FontSelector=Lettertype_selecteren +Font_selection=Lettertype_selecteren for=voor diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 6e7b9114f715..3712929711f5 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -657,15 +657,15 @@ Float=Flyt Float_marked_entries=Sorter_merkede_enheter_\u00f8verst -Font_Family=Familie +Font_family=Familie -Font_Preview=Forh\u00e5ndsvisning +Font_preview=Forh\u00e5ndsvisning -Font_Size=St\u00f8rrelse +Font_size=St\u00f8rrelse -Font_Style=Stil +Font_style=Stil -FontSelector=Fontvelger +Font_selection=Fontvelger for=for diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 1190bb82af99..82e792164288 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -313,11 +313,11 @@ First_select_the_entries_you_want_keys_to_be_generated_for.=Primeiro_selecione_a Fit_table_horizontally_on_screen=Ajustar_tabela_horizontalmente_na_tela Float=Manter_no_topo Float_marked_entries=Flutuar_referências_marcadas -Font_Family=Família_da_fonte -Font_Preview=Previsualização_da_fonte -Font_Size=Tamanho_da_fonte -Font_Style=Estilo_de_fonte -FontSelector=FontSelector +Font_family=Família_da_fonte +Font_preview=Previsualização_da_fonte +Font_size=Tamanho_da_fonte +Font_style=Estilo_de_fonte +Font_selection=Font_selection for=para Format_of_author_and_editor_names=Formato_dos_nomes_do_autor_e_editor Format_String=Formato_de_string diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index c41e1d5b115f..d6c1882ba351 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -581,15 +581,15 @@ Fit_table_horizontally_on_screen=Разместить_горизонтально Float=Нефиксированные Float_marked_entries=Записи_с_метками_как_нефиксированные -Font_Family=Гарнитура_шрифта +Font_family=Гарнитура_шрифта -Font_Preview=Предпросмотр_шрифта +Font_preview=Предпросмотр_шрифта -Font_Size=Кегль +Font_size=Кегль -Font_Style=Начертание_шрифта +Font_style=Начертание_шрифта -FontSelector=Выбор_шрифта +Font_selection=Выбор_шрифта for=для diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 05116b28f173..4cf43a4a5977 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -500,11 +500,11 @@ Float=Visa_först Float_marked_entries=Visa_märkta_poster_först Focus_entry_table=Fokusera_tabellen Follow_DOI_or_URL_link_and_try_to_locate_PDF_full_text_document= -FontSelector=Typsnittsväljare -Font_Family=Typsnittsfamilj -Font_Preview=Typsnittsexempel -Font_Size=Typsnittsstorlek -Font_Style=Typsnittsstil +Font_selection=Typsnittsväljare +Font_family=Typsnittsfamilj +Font_preview=Typsnittsexempel +Font_size=Typsnittsstorlek +Font_style=Typsnittsstil Format_String=Formattera_sträng Format_of_author_and_editor_names=Format_för_författar-_och_redaktörsnamn Format_units_by_adding_non-breaking_separators_and_keeping_the_correct_case_on_search= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index d03ebadce7b4..78a52270d3a1 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -313,11 +313,11 @@ First_select_the_entries_you_want_keys_to_be_generated_for.=Önce_anahtar_oluşt Fit_table_horizontally_on_screen=Tabloyu_ekrana_yatay_sığdır Float=Yüzdür Float_marked_entries=Yüzdür_işaretlenmiş_girdiler -Font_Family=Yazıtipi_Ailesi -Font_Preview=Yazıtipi_Önizleme -Font_Size=Yazıtipi_Boyutu -Font_Style=Yazıtipi_Stili -FontSelector=YazıtipiSeçici +Font_family=Yazıtipi_Ailesi +Font_preview=Yazıtipi_Önizleme +Font_size=Yazıtipi_Boyutu +Font_style=Yazıtipi_Stili +Font_selection=YazıtipiSeçici for=için Format_of_author_and_editor_names=Yazar_ve_düzenleyici_adları_biçemi Format_String=Dizgeyi_Biçimle diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 611ea4edf3d4..1f2e8f06f4e3 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -596,15 +596,15 @@ Fit_table_horizontally_on_screen=Làm_cho_bảng_khít_chiều_ngang_màn_hình Float=Float Float_marked_entries=Các_mục_được_đánh_dấu_là_Float -Font_Family=Họ_phông_chữ +Font_family=Họ_phông_chữ -Font_Preview=Xem_trước_phông_chữ +Font_preview=Xem_trước_phông_chữ -Font_Size=Cỡ_phông_chữ +Font_size=Cỡ_phông_chữ -Font_Style=Kiểu_phông_chữ +Font_style=Kiểu_phông_chữ -FontSelector=Trình_chọn_phông_chữ +Font_selection=Trình_chọn_phông_chữ for=dùng_cho diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 0f3d9a92357f..233dd13cb299 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -308,11 +308,11 @@ Fit_table_horizontally_on_screen=列表宽度填满屏幕宽度 Float=浮动_(结果上浮到最前) Float_marked_entries=浮动高亮显示的记录_(上浮到列表最前) Focus_entry_table=激活记录列表 -FontSelector=字体下拉菜单项 -Font_Family=字体 -Font_Preview=预览字体 -Font_Size=字号 -Font_Style=字体 +Font_selection=字体下拉菜单项 +Font_family=字体 +Font_preview=预览字体 +Font_size=字号 +Font_style=字体 Format_String=格式化简写字串 Format_of_author_and_editor_names=作者和编者的姓名格式 Format_used=使用的格式 diff --git a/src/test/java/net/sf/jabref/MetaDataTest.java b/src/test/java/net/sf/jabref/MetaDataTest.java index 514e87216695..6ed59e9a7a52 100644 --- a/src/test/java/net/sf/jabref/MetaDataTest.java +++ b/src/test/java/net/sf/jabref/MetaDataTest.java @@ -1,6 +1,5 @@ package net.sf.jabref; -import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.TreeMap; @@ -30,7 +29,7 @@ public void serializeNewMetadataReturnsEmptyMap() throws Exception { } @Test - public void serializeSingleSaveAction() throws IOException { + public void serializeSingleSaveAction() { FieldFormatterCleanups saveActions = new FieldFormatterCleanups(true, Collections.singletonList(new FieldFormatterCleanup("title", new LowerCaseFormatter()))); metaData.setSaveActions(saveActions); From 34e8c94f34e702b49d895f05f92fd385231f0850 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 3 Jun 2016 12:02:09 +0200 Subject: [PATCH 129/268] Removed some issues and encapsulated some fields (#1230) --- src/main/java/net/sf/jabref/JabRefGUI.java | 2 +- .../sf/jabref/collab/ChangeDisplayDialog.java | 2 +- .../jabref/exporter/SaveDatabaseAction.java | 42 +- .../sf/jabref/external/AttachFileAction.java | 2 +- .../jabref/external/DroppedFileHandler.java | 8 +- .../external/ExternalFileTypeEditor.java | 2 +- .../jabref/external/FindFullTextAction.java | 2 +- .../jabref/external/SynchronizeFileField.java | 4 +- .../java/net/sf/jabref/gui/BasePanel.java | 516 +++++++++--------- .../sf/jabref/gui/ContentSelectorDialog2.java | 11 +- .../net/sf/jabref/gui/DuplicateSearch.java | 2 +- .../jabref/gui/EntryCustomizationDialog.java | 4 +- .../sf/jabref/gui/FieldContentSelector.java | 10 +- .../sf/jabref/gui/ImportInspectionDialog.java | 2 +- .../java/net/sf/jabref/gui/JabRefFrame.java | 6 +- .../net/sf/jabref/gui/PreambleEditor.java | 2 +- .../java/net/sf/jabref/gui/StringDialog.java | 8 +- .../gui/actions/AutoLinkFilesAction.java | 2 +- .../sf/jabref/gui/actions/CleanupAction.java | 2 +- .../gui/actions/ManageKeywordsAction.java | 2 +- .../gui/actions/MassSetFieldAction.java | 2 +- .../sf/jabref/gui/desktop/JabRefDesktop.java | 2 +- .../jabref/gui/entryeditor/EntryEditor.java | 42 +- .../gui/entryeditor/FieldExtraComponents.java | 8 +- .../jabref/gui/groups/AddToGroupAction.java | 2 +- .../sf/jabref/gui/groups/AutoGroupDialog.java | 3 +- .../net/sf/jabref/gui/groups/GroupDialog.java | 2 +- .../sf/jabref/gui/groups/GroupSelector.java | 40 +- .../gui/groups/RemoveFromGroupAction.java | 2 +- .../jabref/gui/journals/AbbreviateAction.java | 2 +- .../gui/journals/UnabbreviateAction.java | 2 +- .../SearchFixDuplicateLabels.java | 2 +- .../sf/jabref/gui/menus/RightClickMenu.java | 16 +- .../gui/mergeentries/MergeEntriesDialog.java | 2 +- .../gui/mergeentries/MergeEntryDOIDialog.java | 2 +- .../gui/preftabs/EntryEditorPrefsTab.java | 2 +- .../jabref/gui/preftabs/TableColumnsTab.java | 8 +- .../net/sf/jabref/gui/search/SearchBar.java | 8 +- .../sf/jabref/gui/search/SearchWorker.java | 10 +- .../jabref/gui/worker/MarkEntriesAction.java | 2 +- .../jabref/importer/AppendDatabaseAction.java | 2 +- .../importer/EntryFromFileCreatorManager.java | 2 +- .../jabref/importer/EntryFromPDFCreator.java | 2 +- .../migrations/FileLinksUpgradeWarning.java | 2 +- .../net/sf/jabref/pdfimport/PdfImporter.java | 2 +- .../specialfields/SpecialFieldAction.java | 2 +- .../SpecialFieldDatabaseChangeListener.java | 1 - .../jabref/sql/importer/DatabaseImporter.java | 2 + 48 files changed, 413 insertions(+), 392 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefGUI.java b/src/main/java/net/sf/jabref/JabRefGUI.java index 59ad7ff339fe..b4e411e48440 100644 --- a/src/main/java/net/sf/jabref/JabRefGUI.java +++ b/src/main/java/net/sf/jabref/JabRefGUI.java @@ -196,7 +196,7 @@ private void openWindow() { } if (!loaded.isEmpty()) { - new FocusRequester(JabRefGUI.getMainFrame().getCurrentBasePanel().mainTable); + new FocusRequester(JabRefGUI.getMainFrame().getCurrentBasePanel().getMainTable()); } } diff --git a/src/main/java/net/sf/jabref/collab/ChangeDisplayDialog.java b/src/main/java/net/sf/jabref/collab/ChangeDisplayDialog.java index 59f34a9c58b7..3b7056c62323 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeDisplayDialog.java +++ b/src/main/java/net/sf/jabref/collab/ChangeDisplayDialog.java @@ -113,7 +113,7 @@ public ChangeDisplayDialog(JFrame owner, final BasePanel panel, } } ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); if (anyDisabled) { panel.markBaseChanged(); } diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java index 41e4c4d201ae..2d1105031f00 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java @@ -140,7 +140,7 @@ public void run() { } panel.setSaving(false); if (success) { - panel.undoManager.markUnchanged(); + panel.getUndoManager().markUnchanged(); if (!AutoSaveManager.deleteAutoSaveFile(panel)) { //System.out.println("Deletion of autosave file failed"); @@ -191,10 +191,10 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset encoding) if (ex.specificEntry()) { // Error occured during processing of // be. Highlight it: - int row = panel.mainTable.findEntry(ex.getEntry()); + int row = panel.getMainTable().findEntry(ex.getEntry()); int topShow = Math.max(0, row - 3); - panel.mainTable.setRowSelectionInterval(row, row); - panel.mainTable.scrollTo(topShow); + panel.getMainTable().setRowSelectionInterval(row, row); + panel.getMainTable().scrollTo(topShow); panel.showEntry(ex.getEntry()); } else { LOGGER.error("Problem saving file", ex); @@ -320,25 +320,23 @@ public void saveAs() throws Throwable { } } - if (f != null) { - File oldFile = panel.getBibDatabaseContext().getDatabaseFile(); - panel.getBibDatabaseContext().setDatabaseFile(f); - Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, f.getParent()); - runCommand(); - // If the operation failed, revert the file field and return: - if (!success) { - panel.getBibDatabaseContext().setDatabaseFile(oldFile); - return; - } - // Register so we get notifications about outside changes to the file. - try { - panel.setFileMonitorHandle(Globals.fileUpdateMonitor.addUpdateListener(panel, - panel.getBibDatabaseContext().getDatabaseFile())); - } catch (IOException ex) { - LOGGER.error("Problem registering file change notifications", ex); - } - frame.getFileHistory().newFile(panel.getBibDatabaseContext().getDatabaseFile().getPath()); + File oldFile = panel.getBibDatabaseContext().getDatabaseFile(); + panel.getBibDatabaseContext().setDatabaseFile(f); + Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, f.getParent()); + runCommand(); + // If the operation failed, revert the file field and return: + if (!success) { + panel.getBibDatabaseContext().setDatabaseFile(oldFile); + return; + } + // Register so we get notifications about outside changes to the file. + try { + panel.setFileMonitorHandle(Globals.fileUpdateMonitor.addUpdateListener(panel, + panel.getBibDatabaseContext().getDatabaseFile())); + } catch (IOException ex) { + LOGGER.error("Problem registering file change notifications", ex); } + frame.getFileHistory().newFile(panel.getBibDatabaseContext().getDatabaseFile().getPath()); frame.updateEnabledState(); } diff --git a/src/main/java/net/sf/jabref/external/AttachFileAction.java b/src/main/java/net/sf/jabref/external/AttachFileAction.java index e379ab17d0e2..eb43b0533f9f 100644 --- a/src/main/java/net/sf/jabref/external/AttachFileAction.java +++ b/src/main/java/net/sf/jabref/external/AttachFileAction.java @@ -46,7 +46,7 @@ public void action() { UndoableFieldChange ce = new UndoableFieldChange(entry, Globals.FILE_FIELD, entry.getField(Globals.FILE_FIELD), newVal); entry.setField(Globals.FILE_FIELD, newVal); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); } } diff --git a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java index c8f09083c516..c5232f56a50c 100644 --- a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java +++ b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java @@ -137,7 +137,7 @@ public void handleDroppedfile(String fileName, ExternalFileType fileType, BibEnt if (tryXmpImport(fileName, fileType, edits)) { edits.end(); - panel.undoManager.addEdit(edits); + panel.getUndoManager().addEdit(edits); return; } @@ -171,7 +171,7 @@ public void handleDroppedfile(String fileName, ExternalFileType fileType, BibEnt panel.updateEntryEditorIfShowing(); } edits.end(); - panel.undoManager.addEdit(edits); + panel.getUndoManager().addEdit(edits); } @@ -220,7 +220,7 @@ public void linkPdfToEntry(String fileName, BibEntry entry) { panel.markBaseChanged(); } edits.end(); - panel.undoManager.addEdit(edits); + panel.getUndoManager().addEdit(edits); } // Done by MrDlib @@ -444,7 +444,7 @@ private void doLink(BibEntry entry, ExternalFileType fileType, String filename, entry.setField(Globals.FILE_FIELD, newValue); if (edits == null) { - panel.undoManager.addEdit(edit); + panel.getUndoManager().addEdit(edit); } else { edits.addEdit(edit); } diff --git a/src/main/java/net/sf/jabref/external/ExternalFileTypeEditor.java b/src/main/java/net/sf/jabref/external/ExternalFileTypeEditor.java index 0690853c55ca..374b1778bca8 100644 --- a/src/main/java/net/sf/jabref/external/ExternalFileTypeEditor.java +++ b/src/main/java/net/sf/jabref/external/ExternalFileTypeEditor.java @@ -383,7 +383,7 @@ public void actionPerformed(ActionEvent e) { editor.setValues(); editor.setVisible(true); if ((frame != null) && (frame.getCurrentBasePanel() != null)) { - frame.getCurrentBasePanel().mainTable.repaint(); + frame.getCurrentBasePanel().getMainTable().repaint(); } } } diff --git a/src/main/java/net/sf/jabref/external/FindFullTextAction.java b/src/main/java/net/sf/jabref/external/FindFullTextAction.java index ec0e78c73319..e00758c6e4d0 100644 --- a/src/main/java/net/sf/jabref/external/FindFullTextAction.java +++ b/src/main/java/net/sf/jabref/external/FindFullTextAction.java @@ -86,7 +86,7 @@ public void update() { String newValue = tm.getStringRepresentation(); UndoableFieldChange edit = new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue); entry.setField(Globals.FILE_FIELD, newValue); - basePanel.undoManager.addEdit(edit); + basePanel.getUndoManager().addEdit(edit); basePanel.markBaseChanged(); }); } catch (IOException e) { diff --git a/src/main/java/net/sf/jabref/external/SynchronizeFileField.java b/src/main/java/net/sf/jabref/external/SynchronizeFileField.java index 075686f2aa35..0908a6c2c878 100644 --- a/src/main/java/net/sf/jabref/external/SynchronizeFileField.java +++ b/src/main/java/net/sf/jabref/external/SynchronizeFileField.java @@ -241,7 +241,7 @@ public void run() { fileTypes.add(newType); Collections.sort(fileTypes); ExternalFileTypes.getInstance().setExternalFileTypes(fileTypes); - panel.mainTable.repaint(); + panel.getMainTable().repaint(); } } else { // User wants to change the type of this link. @@ -273,7 +273,7 @@ public void run() { if (!changedEntries.isEmpty()) { // Add the undo edit: ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); entriesChangedCount = changedEntries.size(); } diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 7445502a3d6b..9a32b0ebc332 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -184,7 +184,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe // AutoCompleter used in the search bar private AutoCompleter searchAutoCompleter; // The undo manager. - public final CountingUndoManager undoManager = new CountingUndoManager(this); + private final CountingUndoManager undoManager = new CountingUndoManager(this); private final UndoAction undoAction = new UndoAction(); private final RedoAction redoAction = new RedoAction(); @@ -195,9 +195,9 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe private boolean nonUndoableChange; // Used to track whether the base has changed since last save. - public MainTable mainTable; + private MainTable mainTable; - public MainTableFormat tableFormat; + private MainTableFormat tableFormat; private BibEntry showing; @@ -205,7 +205,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe // when a Back or Forward operation is being processed: private boolean backOrForwardInProgress; // To indicate which entry is currently shown. - public final Map entryEditors = new HashMap<>(); + private final Map entryEditors = new HashMap<>(); // in switching between entries. private PreambleEditor preambleEditor; @@ -329,31 +329,7 @@ private void setupActions() { new SaveSelectedAction(SavePreferences.DatabaseSaveType.PLAIN_BIBTEX)); // The action for copying selected entries. - actions.put(Actions.COPY, (BaseAction) () -> { - List bes = mainTable.getSelectedEntries(); - - if (bes.isEmpty()) { - // The user maybe selected a single cell. - // TODO: Check if this can actually happen - int[] rows = mainTable.getSelectedRows(); - int[] cols = mainTable.getSelectedColumns(); - if ((cols.length == 1) && (rows.length == 1)) { - // Copy single value. - Object o = mainTable.getValueAt(rows[0], cols[0]); - if (o != null) { - StringSelection ss = new StringSelection(o.toString()); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); - - output(Localization.lang("Copied cell contents") + '.'); - } - } - } else { - TransferableBibtexEntry trbe = new TransferableBibtexEntry(bes); - // ! look at ClipBoardManager - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trbe, BasePanel.this); - output(formatOutputMessage(Localization.lang("Copied"), bes.size())); - } - }); + actions.put(Actions.COPY, (BaseAction) () -> copy()); //when you modify this action be sure to adjust Actions.DELETE //they are the same except of the Localization, delete confirmation and Actions.COPY call @@ -372,7 +348,7 @@ private void setupActions() { ensureNotShowingBottomPanel(entry); } compound.end(); - undoManager.addEdit(compound); + getUndoManager().addEdit(compound); frame.output(formatOutputMessage(Localization.lang("Cut"), entries.size())); markBaseChanged(); @@ -380,28 +356,7 @@ private void setupActions() { //when you modify this action be sure to adjust Actions.CUT, //they are the same except of the Localization, delete confirmation and Actions.COPY call - actions.put(Actions.DELETE, (BaseAction) () -> { - List entries = mainTable.getSelectedEntries(); - if (entries.isEmpty()) { - return; - } - if (!showDeleteConfirmationDialog(entries.size())) { - return; - } - - NamedCompound compound = new NamedCompound( - (entries.size() > 1 ? Localization.lang("delete entries") : Localization.lang("delete entry"))); - for (BibEntry entry : entries) { - compound.addEdit(new UndoableRemoveEntry(database, entry, BasePanel.this)); - database.removeEntry(entry); - ensureNotShowingBottomPanel(entry); - } - compound.end(); - undoManager.addEdit(compound); - - markBaseChanged(); - frame.output(formatOutputMessage(Localization.lang("Deleted"), entries.size())); - }); + actions.put(Actions.DELETE, (BaseAction) () -> delete()); // The action for pasting entries or cell contents. // - more robust detection of available content flavors (doesn't only look at first one offered) @@ -409,54 +364,7 @@ private void setupActions() { // This allows you to (a) paste entire bibtex entries from a text editor, web browser, etc // (b) copy and paste entries between multiple instances of JabRef (since // only the text representation seems to get as far as the X clipboard, at least on my system) - actions.put(Actions.PASTE, (BaseAction) () -> { - Collection bes = new ClipBoardManager().extractBibEntriesFromClipboard(); - - // finally we paste in the entries (if any), which either came from TransferableBibtexEntries - // or were parsed from a string - if (!bes.isEmpty()) { - - NamedCompound ce = new NamedCompound( - (bes.size() > 1 ? Localization.lang("paste entries") : Localization.lang("paste entry"))); - - // Store the first inserted bibtexentry. - // bes[0] does not work as bes[0] is first clonded, - // then inserted. - // This entry is used to open up an entry editor - // for the first inserted entry. - BibEntry firstBE = null; - - for (BibEntry be1 : bes) { - - BibEntry be = (BibEntry) be1.clone(); - if (firstBE == null) { - firstBE = be; - } - UpdateField.setAutomaticFields(be, Globals.prefs.getBoolean(JabRefPreferences.OVERWRITE_OWNER), - Globals.prefs.getBoolean(JabRefPreferences.OVERWRITE_TIME_STAMP)); - - // We have to clone the - // entries, since the pasted - // entries must exist - // independently of the copied - // ones. - be.setId(IdGenerator.next()); - database.insertEntry(be); - - ce.addEdit(new UndoableInsertEntry(database, be, BasePanel.this)); - - } - ce.end(); - undoManager.addEdit(ce); - output(formatOutputMessage(Localization.lang("Pasted"), bes.size())); - markBaseChanged(); - - if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_OPEN_FORM)) { - selectionListener.editSignalled(firstBE); - } - highlightEntry(firstBE); - } - }); + actions.put(Actions.PASTE, (BaseAction) () -> paste()); actions.put(Actions.SELECT_ALL, (BaseAction) mainTable::selectAll); @@ -671,7 +579,7 @@ public void run() { bes.getCiteKey())); } ce.end(); - undoManager.addEdit(ce); + getUndoManager().addEdit(ce); } // Run third, on EDT: @@ -710,143 +618,19 @@ public void update() { actions.put(Actions.SEARCH, (BaseAction) searchBar::focus); // The action for copying the selected entry's key. - actions.put(Actions.COPY_KEY, (BaseAction) () -> { - List bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - storeCurrentEdit(); - List keys = new ArrayList<>(bes.size()); - // Collect all non-null keys. - for (BibEntry be : bes) { - if (be.getCiteKey() != null) { - keys.add(be.getCiteKey()); - } - } - if (keys.isEmpty()) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - StringSelection ss = new StringSelection(String.join(",", keys)); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); - - if (keys.size() == bes.size()) { - // All entries had keys. - output((bes.size() > 1 ? Localization.lang("Copied keys") : Localization.lang("Copied key")) + '.'); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", - Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); - } - } - }); + actions.put(Actions.COPY_KEY, (BaseAction) () -> copyKey()); // The action for copying a cite for the selected entry. - actions.put(Actions.COPY_CITE_KEY, (BaseAction) () -> { - List bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - storeCurrentEdit(); - List keys = new ArrayList<>(bes.size()); - // Collect all non-null keys. - for (BibEntry be : bes) { - if (be.getCiteKey() != null) { - keys.add(be.getCiteKey()); - } - } - if (keys.isEmpty()) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - String sb = String.join(",", keys); - StringSelection ss = new StringSelection("\\cite{" + sb + '}'); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); - - if (keys.size() == bes.size()) { - // All entries had keys. - output(bes.size() > 1 ? Localization.lang("Copied keys") : Localization.lang("Copied key") + '.'); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", - Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); - } - } - }); + actions.put(Actions.COPY_CITE_KEY, (BaseAction) () -> copyCiteKey()); // The action for copying the BibTeX key and the title for the first selected entry - actions.put(Actions.COPY_KEY_AND_TITLE, (BaseAction) () -> { - List bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - storeCurrentEdit(); - - // OK: in a future version, this string should be configurable to allow arbitrary exports - StringReader sr = new StringReader( - "\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); - Layout layout; - try { - layout = new LayoutHelper(sr, Globals.journalAbbreviationLoader.getRepository()) - .getLayoutFromText(); - } catch (IOException e) { - LOGGER.info("Could not get layout", e); - return; - } - - StringBuilder sb = new StringBuilder(); - - int copied = 0; - // Collect all non-null keys. - for (BibEntry be : bes) { - if (be.getCiteKey() != null) { - copied++; - sb.append(layout.doLayout(be, database)); - } - } - - if (copied == 0) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - final StringSelection ss = new StringSelection(sb.toString()); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); - - if (copied == bes.size()) { - // All entries had keys. - output((bes.size() > 1 ? Localization.lang("Copied keys") : Localization.lang("Copied key")) + '.'); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", - Integer.toString(bes.size() - copied), Integer.toString(bes.size()))); - } - } - }); + actions.put(Actions.COPY_KEY_AND_TITLE, (BaseAction) () -> copyKeyAndTitle()); actions.put(Actions.MERGE_DATABASE, new AppendDatabaseAction(frame, this)); actions.put(Actions.ADD_FILE_LINK, new AttachFileAction(this)); - actions.put(Actions.OPEN_EXTERNAL_FILE, - (BaseAction) () -> JabRefExecutorService.INSTANCE.execute(() -> { - final List bes = mainTable.getSelectedEntries(); - if (bes.size() != 1) { - output(Localization.lang("This operation requires exactly one item to be selected.")); - return; - } - - final BibEntry entry = bes.get(0); - if (!entry.hasField(Globals.FILE_FIELD)) { - // no bibtex field - new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); - return; - } - FileListTableModel tableModel = new FileListTableModel(); - tableModel.setContent(entry.getField(Globals.FILE_FIELD)); - if (tableModel.getRowCount() == 0) { - // content in bibtex field is not readable - new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); - return; - } - FileListEntry flEntry = tableModel.getEntry(0); - ExternalFileMenuItem item = new ExternalFileMenuItem(frame(), entry, "", flEntry.link, - flEntry.type.get().getIcon(), bibDatabaseContext, flEntry.type); - item.openLink(); - })); + actions.put(Actions.OPEN_EXTERNAL_FILE, (BaseAction) () -> openExternalFile()); actions.put(Actions.OPEN_FOLDER, (BaseAction) () -> JabRefExecutorService.INSTANCE.execute(() -> { final List files = FileUtil.getListOfLinkedFiles(mainTable.getSelectedEntries(), @@ -889,7 +673,7 @@ public void update() { + (counter == 1 ? Localization.lang("occurrence") : Localization.lang("occurrences")) + '.'); if (counter > 0) { ce.end(); - undoManager.addEdit(ce); + getUndoManager().addEdit(ce); markBaseChanged(); } }); @@ -933,7 +717,7 @@ public void update() { EntryMarker.unmarkEntry(be, false, database, ce); } ce.end(); - undoManager.addEdit(ce); + getUndoManager().addEdit(ce); markBaseChanged(); String outputStr; if (bes.size() == 1) { @@ -954,7 +738,7 @@ public void update() { EntryMarker.unmarkEntry(be, false, database, ce); } ce.end(); - undoManager.addEdit(ce); + getUndoManager().addEdit(ce); markBaseChanged(); output(Localization.lang("Unmarked all entries")); }); @@ -1010,8 +794,7 @@ public void update() { actions.put(Actions.SWITCH_PREVIEW, (BaseAction) selectionListener::switchPreview); actions.put(Actions.MANAGE_SELECTORS, (BaseAction) () -> { - ContentSelectorDialog2 csd = new ContentSelectorDialog2(frame, frame, BasePanel.this, false, - bibDatabaseContext.getMetaData(), null); + ContentSelectorDialog2 csd = new ContentSelectorDialog2(frame, frame, BasePanel.this, false, null); csd.setLocationRelativeTo(frame); csd.setVisible(true); }); @@ -1038,6 +821,239 @@ public void update() { actions.put(Actions.DOWNLOAD_FULL_TEXT, new FindFullTextAction(this)); } + private void copy() { + List bes = mainTable.getSelectedEntries(); + + if (bes.isEmpty()) { + // The user maybe selected a single cell. + // TODO: Check if this can actually happen + int[] rows = mainTable.getSelectedRows(); + int[] cols = mainTable.getSelectedColumns(); + if ((cols.length == 1) && (rows.length == 1)) { + // Copy single value. + Object o = mainTable.getValueAt(rows[0], cols[0]); + if (o != null) { + StringSelection ss = new StringSelection(o.toString()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); + + output(Localization.lang("Copied cell contents") + '.'); + } + } + } else { + TransferableBibtexEntry trbe = new TransferableBibtexEntry(bes); + // ! look at ClipBoardManager + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trbe, BasePanel.this); + output(formatOutputMessage(Localization.lang("Copied"), bes.size())); + } + } + + //when you modify this action be sure to adjust Actions.CUT, + //they are the same except of the Localization, delete confirmation and Actions.COPY call + private void delete() { + List entries = mainTable.getSelectedEntries(); + if (entries.isEmpty()) { + return; + } + if (!showDeleteConfirmationDialog(entries.size())) { + return; + } + + NamedCompound compound = new NamedCompound( + (entries.size() > 1 ? Localization.lang("delete entries") : Localization.lang("delete entry"))); + for (BibEntry entry : entries) { + compound.addEdit(new UndoableRemoveEntry(database, entry, BasePanel.this)); + database.removeEntry(entry); + ensureNotShowingBottomPanel(entry); + } + compound.end(); + getUndoManager().addEdit(compound); + + markBaseChanged(); + frame.output(formatOutputMessage(Localization.lang("Deleted"), entries.size())); + } + + private void paste() { + Collection bes = new ClipBoardManager().extractBibEntriesFromClipboard(); + + // finally we paste in the entries (if any), which either came from TransferableBibtexEntries + // or were parsed from a string + if (!bes.isEmpty()) { + + NamedCompound ce = new NamedCompound( + (bes.size() > 1 ? Localization.lang("paste entries") : Localization.lang("paste entry"))); + + // Store the first inserted bibtexentry. + // bes[0] does not work as bes[0] is first clonded, + // then inserted. + // This entry is used to open up an entry editor + // for the first inserted entry. + BibEntry firstBE = null; + + for (BibEntry be1 : bes) { + + BibEntry be = (BibEntry) be1.clone(); + if (firstBE == null) { + firstBE = be; + } + UpdateField.setAutomaticFields(be, Globals.prefs.getBoolean(JabRefPreferences.OVERWRITE_OWNER), + Globals.prefs.getBoolean(JabRefPreferences.OVERWRITE_TIME_STAMP)); + + // We have to clone the + // entries, since the pasted + // entries must exist + // independently of the copied + // ones. + be.setId(IdGenerator.next()); + database.insertEntry(be); + + ce.addEdit(new UndoableInsertEntry(database, be, BasePanel.this)); + + } + ce.end(); + getUndoManager().addEdit(ce); + output(formatOutputMessage(Localization.lang("Pasted"), bes.size())); + markBaseChanged(); + + if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_OPEN_FORM)) { + selectionListener.editSignalled(firstBE); + } + highlightEntry(firstBE); + } + } + + private void copyCiteKey() { + List bes = mainTable.getSelectedEntries(); + if (!bes.isEmpty()) { + storeCurrentEdit(); + List keys = new ArrayList<>(bes.size()); + // Collect all non-null keys. + for (BibEntry be : bes) { + if (be.getCiteKey() != null) { + keys.add(be.getCiteKey()); + } + } + if (keys.isEmpty()) { + output(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + String sb = String.join(",", keys); + StringSelection ss = new StringSelection("\\cite{" + sb + '}'); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); + + if (keys.size() == bes.size()) { + // All entries had keys. + output(bes.size() > 1 ? Localization.lang("Copied keys") : Localization.lang("Copied key") + '.'); + } else { + output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); + } + } + } + + private void copyKey() { + List bes = mainTable.getSelectedEntries(); + if (!bes.isEmpty()) { + storeCurrentEdit(); + List keys = new ArrayList<>(bes.size()); + // Collect all non-null keys. + for (BibEntry be : bes) { + if (be.getCiteKey() != null) { + keys.add(be.getCiteKey()); + } + } + if (keys.isEmpty()) { + output(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + StringSelection ss = new StringSelection(String.join(",", keys)); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); + + if (keys.size() == bes.size()) { + // All entries had keys. + output((bes.size() > 1 ? Localization.lang("Copied keys") : Localization.lang("Copied key")) + '.'); + } else { + output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); + } + } + } + + private void copyKeyAndTitle() { + List bes = mainTable.getSelectedEntries(); + if (!bes.isEmpty()) { + storeCurrentEdit(); + + // OK: in a future version, this string should be configurable to allow arbitrary exports + StringReader sr = new StringReader( + "\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); + Layout layout; + try { + layout = new LayoutHelper(sr, Globals.journalAbbreviationLoader.getRepository()) + .getLayoutFromText(); + } catch (IOException e) { + LOGGER.info("Could not get layout", e); + return; + } + + StringBuilder sb = new StringBuilder(); + + int copied = 0; + // Collect all non-null keys. + for (BibEntry be : bes) { + if (be.getCiteKey() != null) { + copied++; + sb.append(layout.doLayout(be, database)); + } + } + + if (copied == 0) { + output(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + final StringSelection ss = new StringSelection(sb.toString()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, BasePanel.this); + + if (copied == bes.size()) { + // All entries had keys. + output((bes.size() > 1 ? Localization.lang("Copied keys") : Localization.lang("Copied key")) + '.'); + } else { + output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(bes.size() - copied), Integer.toString(bes.size()))); + } + } + } + + private void openExternalFile() { + JabRefExecutorService.INSTANCE.execute(() -> { + final List bes = mainTable.getSelectedEntries(); + if (bes.size() != 1) { + output(Localization.lang("This operation requires exactly one item to be selected.")); + return; + } + + final BibEntry entry = bes.get(0); + if (!entry.hasField(Globals.FILE_FIELD)) { + // no bibtex field + new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); + return; + } + FileListTableModel tableModel = new FileListTableModel(); + tableModel.setContent(entry.getField(Globals.FILE_FIELD)); + if (tableModel.getRowCount() == 0) { + // content in bibtex field is not readable + new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); + return; + } + FileListEntry flEntry = tableModel.getEntry(0); + ExternalFileMenuItem item = new ExternalFileMenuItem(frame(), entry, "", flEntry.link, + flEntry.type.get().getIcon(), bibDatabaseContext, flEntry.type); + item.openLink(); + }); + } + /** * This method is called from JabRefFrame if a database specific action is requested by the user. Runs the command * if it is defined, or prints an error message to the standard error stream. @@ -1175,7 +1191,7 @@ public void registerUndoableChanges(SaveSession session) { } ce.end(); if (ce.hasEdits()) { - undoManager.addEdit(ce); + getUndoManager().addEdit(ce); } } @@ -1207,7 +1223,7 @@ public BibEntry newEntry(EntryType type) { UpdateField.setAutomaticFields(list, true, true); // Create an UndoableInsertEntry object. - undoManager.addEdit(new UndoableInsertEntry(database, be, BasePanel.this)); + getUndoManager().addEdit(new UndoableInsertEntry(database, be, BasePanel.this)); output(Localization.lang("Added new '%0' entry.", actualType.getName().toLowerCase())); // We are going to select the new entry. Before that, make sure that we are in @@ -1361,7 +1377,7 @@ public void insertEntry(final BibEntry bibEntry) { UpdateField.setAutomaticFields(bibEntry, true, true); } // Create an UndoableInsertEntry object. - undoManager.addEdit(new UndoableInsertEntry(database, bibEntry, BasePanel.this)); + getUndoManager().addEdit(new UndoableInsertEntry(database, bibEntry, BasePanel.this)); output(Localization.lang("Added new '%0' entry.", bibEntry.getType())); markBaseChanged(); // The database just changed. @@ -1869,7 +1885,7 @@ public void markNonUndoableBaseChanged() { } private synchronized void markChangedOrUnChanged() { - if (undoManager.hasChanged()) { + if (getUndoManager().hasChanged()) { if (!baseChanged) { markBaseChanged(); } @@ -1936,7 +1952,7 @@ private void changeType(List entries, String newType) { output(formatOutputMessage(Localization.lang("Changed type to '%0' for", newType), entries.size())); compound.end(); - undoManager.addEdit(compound); + getUndoManager().addEdit(compound); markBaseChanged(); updateEntryEditorIfShowing(); } @@ -1984,7 +2000,7 @@ public void autoGenerateKeysBeforeSaving() { // Store undo information, if any: if (any) { ce.end(); - undoManager.addEdit(ce); + getUndoManager().addEdit(ce); } } } @@ -2029,8 +2045,8 @@ public void action() { storeCurrentEdit(); } } - String name = undoManager.getUndoPresentationName(); - undoManager.undo(); + String name = getUndoManager().getUndoPresentationName(); + getUndoManager().undo(); markBaseChanged(); frame.output(name); } catch (CannotUndoException ex) { @@ -2113,8 +2129,8 @@ public void action() { storeCurrentEdit(); } - String name = undoManager.getRedoPresentationName(); - undoManager.redo(); + String name = getUndoManager().getRedoPresentationName(); + getUndoManager().redo(); markBaseChanged(); frame.output(name); } catch (CannotRedoException ex) { @@ -2452,4 +2468,16 @@ private void setPreviewActiveBasePanels(boolean enabled) { frame.getBasePanelAt(i).setPreviewActive(enabled); } } + + public CountingUndoManager getUndoManager() { + return undoManager; + } + + public MainTable getMainTable() { + return mainTable; + } + + public Map getEntryEditors() { + return entryEditors; + } } diff --git a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java index aa60f27295a0..aa22ed1ac1ff 100644 --- a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java +++ b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java @@ -63,8 +63,8 @@ class ContentSelectorDialog2 extends JDialog { private final JPanel fieldNamePan = new JPanel(); private final JPanel wordEditPan = new JPanel(); - private final String WORD_FIRSTLINE_TEXT = Localization.lang(""); + private static final String FIELD_FIRST_LINE = Localization.lang(""); private final MetaData metaData; private String currentField; private final JabRefFrame frame; @@ -96,14 +96,13 @@ class ContentSelectorDialog2 extends JDialog { * @param frame the JabRef Frame * @param panel the currently selected BasePanel * @param modal should this dialog be modal? - * @param metaData The metadata of the current database * @param fieldName the field this selector is initialized for. May be null. */ - public ContentSelectorDialog2(Window owner, JabRefFrame frame, BasePanel panel, boolean modal, MetaData metaData, + public ContentSelectorDialog2(Window owner, JabRefFrame frame, BasePanel panel, boolean modal, String fieldName) { super(owner, Localization.lang("Setup selectors")); this.setModal(modal); - this.metaData = metaData; + this.metaData = panel.getBibDatabaseContext().getMetaData(); this.frame = frame; this.panel = panel; this.currentField = fieldName; @@ -294,7 +293,7 @@ private void applyChanges() { } } - // System.out.println("TODO: remove metadata for removed selector field."); + // TODO: remove metadata for removed selector field. panel.markNonUndoableBaseChanged(); // Update all selectors in the current BasePanel. diff --git a/src/main/java/net/sf/jabref/gui/DuplicateSearch.java b/src/main/java/net/sf/jabref/gui/DuplicateSearch.java index 06f8786bd015..7719464e1f74 100644 --- a/src/main/java/net/sf/jabref/gui/DuplicateSearch.java +++ b/src/main/java/net/sf/jabref/gui/DuplicateSearch.java @@ -156,7 +156,7 @@ public void run() { + Localization.lang("pairs processed") + ": " + dupliC); } ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } diff --git a/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java b/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java index 33791ee18ed5..3deb0b374f21 100644 --- a/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java @@ -393,7 +393,7 @@ private void updateTypesForEntries(String typeName) { for (BasePanel bp : frame.getBasePanelList()) { // Invalidate associated cached entry editor - bp.entryEditors.remove(typeName); + bp.getEntryEditors().remove(typeName); for (BibEntry entry : bp.getDatabase().getEntries()) { EntryTypes.getType(entry.getType(), bibDatabaseContext.getMode()).ifPresent(entry::setType); @@ -404,7 +404,7 @@ private void updateTypesForEntries(String typeName) { private void updateTables() { for (BasePanel basePanel : frame.getBasePanelList()) { - ((javax.swing.table.AbstractTableModel) basePanel.mainTable.getModel()).fireTableDataChanged(); + ((javax.swing.table.AbstractTableModel) basePanel.getMainTable().getModel()).fireTableDataChanged(); } } diff --git a/src/main/java/net/sf/jabref/gui/FieldContentSelector.java b/src/main/java/net/sf/jabref/gui/FieldContentSelector.java index 5b012b841002..dc0de7eeb4d6 100644 --- a/src/main/java/net/sf/jabref/gui/FieldContentSelector.java +++ b/src/main/java/net/sf/jabref/gui/FieldContentSelector.java @@ -68,10 +68,6 @@ public class FieldContentSelector extends JComponent { * @param editor * The entry editor which will be appended by the text selected * by the user from the combobox. - * @param metaData - * The metadata that contains the list of items to display in the - * combobox under the key Globals.SELECTOR_META_PREFIX + - * editor.getFieldName(). * @param action * The action that will be performed to after an item from the * combobox has been appended to the text in the entryeditor. @@ -80,12 +76,12 @@ public class FieldContentSelector extends JComponent { * button. */ public FieldContentSelector(JabRefFrame frame, final BasePanel panel, - Window owner, final FieldEditor editor, final MetaData metaData, + Window owner, final FieldEditor editor, final AbstractAction action, boolean horizontalLayout, String delimiter) { this.editor = editor; - this.metaData = metaData; + this.metaData = panel.getBibDatabaseContext().getMetaData(); this.action = action; this.delimiter = delimiter; @@ -155,7 +151,7 @@ public void actionPerformed(ActionEvent actionEvent) { add(manage); manage.addActionListener(e -> { - ContentSelectorDialog2 csd = new ContentSelectorDialog2(owner, frame, panel, true, metaData, + ContentSelectorDialog2 csd = new ContentSelectorDialog2(owner, frame, panel, true, editor.getFieldName()); csd.setLocationRelativeTo(frame); diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 2e6ccbae29fb..97d082028a50 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -740,7 +740,7 @@ private void addSelectedEntries(NamedCompound ce, final List selected) } ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } private boolean addToGroups(NamedCompound ce, BibEntry entry, Set groups) { diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 72b787f96d82..8e79c51384cf 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -629,14 +629,14 @@ public void windowClosing(WindowEvent e) { groupToggle.setSelected(sidePaneManager.isComponentVisible("groups")); previewToggle.setSelected(Globals.prefs.getBoolean(JabRefPreferences.PREVIEW_ENABLED)); fetcherToggle.setSelected(sidePaneManager.isComponentVisible(generalFetcher.getTitle())); - Globals.focusListener.setFocused(bp.mainTable); + Globals.focusListener.setFocused(bp.getMainTable()); setWindowTitle(); editModeAction.initName(); // Update search autocompleter with information for the correct database: bp.updateSearchManager(); // Set correct enabled state for Back and Forward actions: bp.setBackAndForwardEnabledState(); - new FocusRequester(bp.mainTable); + new FocusRequester(bp.getMainTable()); }); //Note: The registration of Apple event is at the end of initialization, because @@ -1735,7 +1735,7 @@ public FileHistoryMenu getFileHistory() { public void removeCachedEntryEditors() { for (int j = 0; j < tabbedPane.getTabCount(); j++) { BasePanel bp = (BasePanel) tabbedPane.getComponentAt(j); - bp.entryEditors.clear(); + bp.getEntryEditors().clear(); } } diff --git a/src/main/java/net/sf/jabref/gui/PreambleEditor.java b/src/main/java/net/sf/jabref/gui/PreambleEditor.java index f9b220e78110..c8caf09fe234 100644 --- a/src/main/java/net/sf/jabref/gui/PreambleEditor.java +++ b/src/main/java/net/sf/jabref/gui/PreambleEditor.java @@ -175,7 +175,7 @@ public void actionPerformed(ActionEvent e) { } if (set) { - panel.undoManager.addEdit(new UndoablePreambleChange + panel.getUndoManager().addEdit(new UndoablePreambleChange (base, panel, base.getPreamble(), toSet)); base.setPreamble(toSet); if ((toSet == null) || toSet.isEmpty()) { diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index 6d8fcf1159ca..51f4b3647275 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -253,7 +253,7 @@ public void setValueAt(Object value, int row, int col) { } else { // Store undo information. BibtexString subject = strings.get(row); - panel.undoManager.addEdit( + panel.getUndoManager().addEdit( new UndoableStringChange(panel, subject, true, subject.getName(), (String) value)); subject.setName((String) value); panel.markBaseChanged(); @@ -271,7 +271,7 @@ public void setValueAt(Object value, int row, int col) { return; } // Store undo information. - panel.undoManager.addEdit( + panel.getUndoManager().addEdit( new UndoableStringChange(panel, subject, false, subject.getContent(), (String) value)); subject.setContent((String) value); @@ -377,7 +377,7 @@ public void actionPerformed(ActionEvent e) { BibtexString bs = new BibtexString(newId, name, ""); // Store undo information: - panel.undoManager.addEdit(new UndoableInsertString(panel, panel.getDatabase(), bs)); + panel.getUndoManager().addEdit(new UndoableInsertString(panel, panel.getDatabase(), bs)); base.addString(bs); refreshTable(); @@ -446,7 +446,7 @@ public void actionPerformed(ActionEvent e) { base.removeString(subject.getId()); } ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); refreshTable(); if (!base.hasNoStrings()) { diff --git a/src/main/java/net/sf/jabref/gui/actions/AutoLinkFilesAction.java b/src/main/java/net/sf/jabref/gui/actions/AutoLinkFilesAction.java index ac17f9ba4c55..8a020319626a 100644 --- a/src/main/java/net/sf/jabref/gui/actions/AutoLinkFilesAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/AutoLinkFilesAction.java @@ -46,7 +46,7 @@ public void actionPerformed(ActionEvent event) { // entry has been updated in Util.autoSetLinks, only treat nc and status message if (nc.hasEdits()) { nc.end(); - JabRefGUI.getMainFrame().getCurrentBasePanel().undoManager.addEdit(nc); + JabRefGUI.getMainFrame().getCurrentBasePanel().getUndoManager().addEdit(nc); JabRefGUI.getMainFrame().getCurrentBasePanel().markBaseChanged(); } JabRefGUI.getMainFrame().output(Localization.lang("Finished automatically setting external links.")); diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java index a8886077a5a5..b6087fe40d01 100644 --- a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java @@ -111,7 +111,7 @@ public void run() { ce.end(); if (ce.hasEdits()) { modifiedEntriesCount++; - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } } } diff --git a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java index 18c09923166c..4b2763b653a2 100644 --- a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java @@ -304,7 +304,7 @@ public void actionPerformed(ActionEvent e) { } NamedCompound ce = updateKeywords(bp.getSelectedEntries(), keywordsToAdd, keywordsToRemove); - bp.undoManager.addEdit(ce); + bp.getUndoManager().addEdit(ce); bp.markBaseChanged(); } diff --git a/src/main/java/net/sf/jabref/gui/actions/MassSetFieldAction.java b/src/main/java/net/sf/jabref/gui/actions/MassSetFieldAction.java index 0a4b875862df..81227b0b739a 100644 --- a/src/main/java/net/sf/jabref/gui/actions/MassSetFieldAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/MassSetFieldAction.java @@ -247,7 +247,7 @@ public void actionPerformed(ActionEvent e) { } } ce.end(); - bp.undoManager.addEdit(ce); + bp.getUndoManager().addEdit(ce); bp.markBaseChanged(); } diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index 8a577b8dbadd..943db8b69dac 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -233,7 +233,7 @@ public static boolean openExternalFileUnknown(JabRefFrame frame, BibEntry entry, String newValue = tModel.getStringRepresentation(); UndoableFieldChange ce = new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue); entry.setField(Globals.FILE_FIELD, newValue); - frame.getCurrentBasePanel().undoManager.addEdit(ce); + frame.getCurrentBasePanel().getUndoManager().addEdit(ce); frame.getCurrentBasePanel().markBaseChanged(); // Finally, open the link: return openExternalFileAnyFormat(databaseContext, flEntry.link, flEntry.type); diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index c8af85397290..93d8a0f7cc0c 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -571,12 +571,12 @@ public void updateSource() { // - ILC (16/02/2010) - ////////////////////////////////////////////////////////// SwingUtilities.invokeLater(() -> { - final int row = panel.mainTable.findEntry(entry); + final int row = panel.getMainTable().findEntry(entry); if (row >= 0) { - if (panel.mainTable.getSelectedRowCount() == 0) { - panel.mainTable.setRowSelectionInterval(row, row); + if (panel.getMainTable().getSelectedRowCount() == 0) { + panel.getMainTable().setRowSelectionInterval(row, row); } - panel.mainTable.ensureVisible(row); + panel.getMainTable().ensureVisible(row); } }); } catch (IOException ex) { @@ -687,8 +687,8 @@ public void setEnabled(boolean enabled) { */ private void scrollTo(int row) { movingToDifferentEntry = true; - panel.mainTable.setRowSelectionInterval(row, row); - panel.mainTable.ensureVisible(row); + panel.getMainTable().setRowSelectionInterval(row, row); + panel.getMainTable().ensureVisible(row); } /** @@ -833,7 +833,7 @@ private boolean storeSource() { return true; } - panel.undoManager.addEdit(compound); + panel.getUndoManager().addEdit(compound); if (duplicateWarning) { warnDuplicateBibtexkey(); @@ -853,9 +853,9 @@ private boolean storeSource() { panel.markBaseChanged(); SwingUtilities.invokeLater(() -> { - final int row = panel.mainTable.findEntry(entry); + final int row = panel.getMainTable().findEntry(entry); if (row >= 0) { - panel.mainTable.ensureVisible(row); + panel.getMainTable().ensureVisible(row); } }); @@ -1046,7 +1046,7 @@ public void actionPerformed(ActionEvent e) { panel.entryEditorClosing(EntryEditor.this); panel.getDatabase().removeEntry(entry); panel.markBaseChanged(); - panel.undoManager.addEdit(new UndoableRemoveEntry(panel.getDatabase(), entry, panel)); + panel.getUndoManager().addEdit(new UndoableRemoveEntry(panel.getDatabase(), entry, panel)); panel.output(Localization.lang("Deleted entry")); } } @@ -1126,9 +1126,9 @@ public void actionPerformed(ActionEvent event) { ce.addEdit(undoableKeyChange); TimeStamp.doUpdateTimeStamp(entry) .ifPresent(fieldChange -> ce.addEdit(new UndoableFieldChange(fieldChange))); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } else { - panel.undoManager.addEdit(undoableKeyChange); + panel.getUndoManager().addEdit(undoableKeyChange); } textField.setValidBackgroundColor(); @@ -1194,9 +1194,9 @@ public void actionPerformed(ActionEvent event) { TimeStamp.doUpdateTimeStamp(entry) .ifPresent(fieldChange -> ce.addEdit(new UndoableFieldChange(fieldChange))); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } else { - panel.undoManager.addEdit(undoableFieldChange); + panel.getUndoManager().addEdit(undoableFieldChange); } updateSource(); panel.markBaseChanged(); @@ -1223,9 +1223,9 @@ public void actionPerformed(ActionEvent event) { // Should only be done if this editor is currently showing: if (!movingAway && isShowing()) { SwingUtilities.invokeLater(() -> { - final int row = panel.mainTable.findEntry(entry); + final int row = panel.getMainTable().findEntry(entry); if (row >= 0) { - panel.mainTable.ensureVisible(row); + panel.getMainTable().ensureVisible(row); } }); } @@ -1270,7 +1270,7 @@ public NextEntryAction() { @Override public void actionPerformed(ActionEvent e) { - int thisRow = panel.mainTable.findEntry(entry); + int thisRow = panel.getMainTable().findEntry(entry); int newRow; if ((thisRow + 1) < panel.getDatabase().getEntryCount()) { @@ -1283,7 +1283,7 @@ public void actionPerformed(ActionEvent e) { } scrollTo(newRow); - panel.mainTable.setRowSelectionInterval(newRow, newRow); + panel.getMainTable().setRowSelectionInterval(newRow, newRow); } } @@ -1297,7 +1297,7 @@ public PrevEntryAction() { @Override public void actionPerformed(ActionEvent e) { - int thisRow = panel.mainTable.findEntry(entry); + int thisRow = panel.getMainTable().findEntry(entry); int newRow; if ((thisRow - 1) >= 0) { @@ -1311,7 +1311,7 @@ public void actionPerformed(ActionEvent e) { } scrollTo(newRow); - panel.mainTable.setRowSelectionInterval(newRow, newRow); + panel.getMainTable().setRowSelectionInterval(newRow, newRow); } } @@ -1362,7 +1362,7 @@ public void actionPerformed(ActionEvent e) { LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry); // Store undo information: - panel.undoManager.addEdit(new UndoableKeyChange(panel.getDatabase(), entry, (String) oldValue, entry.getCiteKey())); + panel.getUndoManager().addEdit(new UndoableKeyChange(panel.getDatabase(), entry, (String) oldValue, entry.getCiteKey())); // here we update the field String bibtexKeyData = entry.getCiteKey(); diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index 96d97966aca9..9fe7087c9447 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -82,8 +82,8 @@ public static Optional getJournalExtraComponent(JabRefFrame frame, B JPanel controls = new JPanel(); controls.setLayout(new BorderLayout()); if (!panel.getBibDatabaseContext().getMetaData().getContentSelectors(editor.getFieldName()).isEmpty()) { - FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor, panel.getBibDatabaseContext().getMetaData(), - storeFieldAction, false, ", "); + FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor, storeFieldAction, false, + ", "); contentSelectors.add(ws); controls.add(ws, BorderLayout.NORTH); } @@ -100,7 +100,7 @@ public static Optional getJournalExtraComponent(JabRefFrame frame, B if (s != null) { editor.setText(s); storeFieldAction.actionPerformed(new ActionEvent(editor, 0, "")); - panel.undoManager.addEdit(new UndoableFieldChange(entry, editor.getFieldName(), text, s)); + panel.getUndoManager().addEdit(new UndoableFieldChange(entry, editor.getFieldName(), text, s)); } } }); @@ -332,7 +332,7 @@ public static Optional getURLExtraComponent(FieldEditor fieldEditor, */ public static Optional getSelectorExtraComponent(JabRefFrame frame, BasePanel panel, FieldEditor editor, Set contentSelectors, StoreFieldAction storeFieldAction) { - FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor, panel.getBibDatabaseContext().getMetaData(), + FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor, storeFieldAction, false, InternalBibtexFields.getFieldExtras(editor.getFieldName()) .contains(FieldProperties.PERSON_NAMES) ? " and " : ", "); diff --git a/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java b/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java index aec5161e006f..779d9eb62572 100644 --- a/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java +++ b/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java @@ -79,7 +79,7 @@ public void actionPerformed(ActionEvent evt) { undoAll.end(); - panel.undoManager.addEdit(undoAll); + panel.getUndoManager().addEdit(undoAll); panel.markBaseChanged(); panel.updateEntryEditorIfShowing(); panel.getGroupSelector().valueChanged(null); diff --git a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java index ed2a2c30cc3c..808a2f0b02cd 100644 --- a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java @@ -132,11 +132,10 @@ public void actionPerformed(ActionEvent e) { panel.markBaseChanged(); // a change always occurs frame.output(Localization.lang("Created groups.")); ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } catch (ParseException exception) { frame.showMessage(exception.getLocalizedMessage()); } - } }; remove.addActionListener(okListener); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index bfd569fe2192..815b5a9d3e5f 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -174,7 +174,7 @@ public GroupDialog(JabRefFrame jabrefFrame, BasePanel basePanel, builderKG.append(Localization.lang("Keyword")); builderKG.append(m_kgSearchTerm); builderKG.append(new FieldContentSelector(jabrefFrame, m_basePanel, this, - m_kgSearchTerm, m_basePanel.getBibDatabaseContext().getMetaData(), null, true, ", ")); + m_kgSearchTerm, null, true, ", ")); builderKG.nextLine(); builderKG.append(m_kgCaseSensitive, 3); builderKG.nextLine(); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 4650c9b44778..bb5cd591e6b3 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -258,7 +258,7 @@ public void stateChanged(ChangeEvent e) { gd.setVisible(true); if (gd.okPressed()) { AbstractGroup newGroup = gd.getResultingGroup(); - groupsRoot.addNewGroup(newGroup, panel.undoManager); + groupsRoot.addNewGroup(newGroup, panel.getUndoManager()); panel.markBaseChanged(); frame.output(Localization.lang("Created group \"%0\".", newGroup.getName())); } @@ -549,7 +549,7 @@ private void annotationEvent(GroupTreeNodeViewModel node) { if (editModeIndicator) { LOGGER.info("Performing annotation " + node.getName()); List entries = panel.getSelectedEntries(); - node.changeEntriesTo(entries, panel.undoManager); + node.changeEntriesTo(entries, panel.getUndoManager()); panel.markBaseChanged(); panel.updateEntryEditorIfShowing(); updateShownEntriesAccordingToSelectedGroups(); @@ -562,7 +562,7 @@ public void valueChanged(TreeSelectionEvent e) { return; // ignore this event (happens for example if the file was closed) } if (getLeafsOfSelection().stream().allMatch(GroupTreeNodeViewModel::isAllEntriesGroup)) { - panel.mainTable.getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); + panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); if (showOverlappingGroups.isSelected()) { groupsTree.setOverlappingGroups(Collections.emptyList()); } @@ -636,13 +636,13 @@ public void run() { public void update() { // Show the result in the chosen way: if (hideNonHits.isSelected()) { - panel.mainTable.getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.FILTER); + panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.FILTER); } else if (grayOut.isSelected()) { - panel.mainTable.getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.FLOAT); + panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.FLOAT); } - panel.mainTable.getTableModel().updateSortOrder(); - panel.mainTable.getTableModel().updateGroupFilter(); - panel.mainTable.scrollTo(0); + panel.getMainTable().getTableModel().updateSortOrder(); + panel.getMainTable().getTableModel().updateGroupFilter(); + panel.getMainTable().scrollTo(0); if (showOverlappingGroupsP) { showOverlappingGroups(matches); @@ -715,7 +715,7 @@ public int getRescalingWeight() { @Override public void componentClosing() { if (panel != null) {// panel may be null if no file is open any more - panel.mainTable.getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); + panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); } frame.groupToggle.setSelected(false); } @@ -792,13 +792,13 @@ public void actionPerformed(ActionEvent e) { revalidateGroups(node); // Store undo information. if (undoAddPreviousEntries == null) { - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); } else { NamedCompound nc = new NamedCompound("Modify Group"); nc.addEdit(undo); nc.addEdit(undoAddPreviousEntries); nc.end(); - panel.undoManager.addEdit(nc); + panel.getUndoManager().addEdit(nc); } panel.markBaseChanged(); frame.output(Localization.lang("Modified group \"%0\".", newGroup.getName())); @@ -831,7 +831,7 @@ public void actionPerformed(ActionEvent e) { new GroupTreeNodeViewModel(newNode), UndoableAddOrRemoveGroup.ADD_NODE); groupsTree.expandPath((node == null ? groupsRoot : node).getTreePath()); // Store undo information. - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); frame.output(Localization.lang("Added group \"%0\".", newGroup.getName())); } @@ -858,7 +858,7 @@ public void actionPerformed(ActionEvent e) { new GroupTreeNodeViewModel(newNode), UndoableAddOrRemoveGroup.ADD_NODE); groupsTree.expandPath(node.getTreePath()); // Store undo information. - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); frame.output(Localization.lang("Added group \"%0\".", newGroup.getName())); } @@ -882,7 +882,7 @@ public void actionPerformed(ActionEvent e) { UndoableAddOrRemoveGroup.REMOVE_NODE_AND_CHILDREN); node.getNode().removeFromParent(); // Store undo information. - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); frame.output(Localization.lang("Removed group \"%0\" and its subgroups.", group.getName())); } @@ -907,7 +907,7 @@ public void actionPerformed(ActionEvent e) { node.getNode().removeAllChildren(); //revalidateGroups(); // Store undo information. - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); frame.output(Localization.lang("Removed all subgroups of group \"%0\".", node.getName())); } @@ -934,7 +934,7 @@ public void actionPerformed(ActionEvent e) { node.getNode().moveAllChildrenTo(parent.getNode(), parent.getIndex(node)); // Store undo information. - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); frame.output(Localization.lang("Removed group \"%0\".", group.getName())); } @@ -959,7 +959,7 @@ public void actionPerformed(ActionEvent ae) { final UndoableModifySubtree undo = new UndoableModifySubtree(getGroupTreeRoot(), node, Localization.lang("sort subgroups")); groupsTree.sort(node, false); - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); frame.output(Localization.lang("Sorted immediate subgroups.")); } @@ -977,7 +977,7 @@ public void actionPerformed(ActionEvent ae) { final UndoableModifySubtree undo = new UndoableModifySubtree(getGroupTreeRoot(), node, Localization.lang("sort subgroups")); groupsTree.sort(node, true); - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); frame.output(Localization.lang("Sorted all subgroups recursively.")); } @@ -1156,7 +1156,7 @@ public boolean moveNodeRight(GroupTreeNodeViewModel node, boolean checkSingleSel * @param node The node that has been moved. */ public void concludeMoveGroup(MoveGroupChange moveChange, GroupTreeNodeViewModel node) { - panel.undoManager.addEdit(new UndoableMoveGroup(this.groupsRoot, moveChange)); + panel.getUndoManager().addEdit(new UndoableMoveGroup(this.groupsRoot, moveChange)); panel.markBaseChanged(); frame.output(Localization.lang("Moved group \"%0\".", node.getNode().getGroup().getName())); } @@ -1167,7 +1167,7 @@ public void concludeAssignment(AbstractUndoableEdit undo, GroupTreeNode node, in node.getGroup().getName())); return; } - panel.undoManager.addEdit(undo); + panel.getUndoManager().addEdit(undo); panel.markBaseChanged(); panel.updateEntryEditorIfShowing(); final String groupName = node.getGroup().getName(); diff --git a/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java b/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java index 1c1784c9eb78..fe17c586925d 100644 --- a/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java +++ b/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java @@ -61,7 +61,7 @@ public void actionPerformed(ActionEvent evt) { return; // no changed made } - mPanel.undoManager.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(mNode, undo.get())); + mPanel.getUndoManager().addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(mNode, undo.get())); mPanel.markBaseChanged(); mPanel.updateEntryEditorIfShowing(); mPanel.getGroupSelector().valueChanged(null); diff --git a/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java b/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java index cf1a62e09298..ffebc4c97766 100644 --- a/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java +++ b/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java @@ -67,7 +67,7 @@ public void run() { if (count > 0) { ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); message = Localization.lang("Abbreviated %0 journal names.", String.valueOf(count)); } else { diff --git a/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java b/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java index 1408f7153a78..8d12b4b983b4 100644 --- a/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java +++ b/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java @@ -64,7 +64,7 @@ public void run() { } if (count > 0) { ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); message = Localization.lang("Unabbreviated %0 journal names.", String.valueOf(count)); } else { diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java b/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java index 74fa7ae5a1eb..80d59d04b1ab 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java @@ -111,7 +111,7 @@ public void update() { ce.addEdit(new UndoableKeyChange(panel.getDatabase(), entry, oldKey, entry.getCiteKey())); } ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); } panel.output(Localization.lang("Finished resolving duplicate BibTeX keys. %0 entries modified.", diff --git a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java index 3f07fd161ce9..25cd210f2630 100644 --- a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java @@ -72,8 +72,8 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) { // If only one entry is selected, get a reference to it for adapting the menu. BibEntry be = null; - if (panel.mainTable.getSelectedRowCount() == 1) { - be = panel.mainTable.getSelected().get(0); + if (panel.getMainTable().getSelectedRowCount() == 1) { + be = panel.getMainTable().getSelected().get(0); } addPopupMenuListener(this); @@ -218,11 +218,11 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) { } private boolean areMultipleEntriesSelected() { - return panel.mainTable.getSelectedRowCount() > 1; + return panel.getMainTable().getSelectedRowCount() > 1; } private boolean areExactlyTwoEntriesSelected() { - return panel.mainTable.getSelectedRowCount() == 2; + return panel.getMainTable().getSelectedRowCount() == 2; } /** @@ -267,8 +267,8 @@ public void popupMenuCanceled(PopupMenuEvent e) { } private boolean isFieldSetForSelectedEntry(String fieldname) { - if (panel.mainTable.getSelectedRowCount() == 1) { - BibEntry entry = panel.mainTable.getSelected().get(0); + if (panel.getMainTable().getSelectedRowCount() == 1) { + BibEntry entry = panel.getMainTable().getSelected().get(0); return entry.getFieldNames().contains(fieldname); } else { return false; @@ -276,8 +276,8 @@ private boolean isFieldSetForSelectedEntry(String fieldname) { } private Icon getFileIconForSelectedEntry() { - if (panel.mainTable.getSelectedRowCount() == 1) { - BibEntry entry = panel.mainTable.getSelected().get(0); + if (panel.getMainTable().getSelectedRowCount() == 1) { + BibEntry entry = panel.getMainTable().getSelected().get(0); if(entry.hasField(Globals.FILE_FIELD)) { JLabel label = FileListTableModel.getFirstLabel(entry.getField(Globals.FILE_FIELD)); if (label != null) { diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java index dbd00a16b403..931fe768d498 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java @@ -113,7 +113,7 @@ private void init(List selected) { ce.addEdit(new UndoableRemoveEntry(panel.getDatabase(), two, panel)); panel.getDatabase().removeEntry(two); ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.output(Localization.lang("Merged entries")); dispose(); }); diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java index b3df25b126a0..ca2d0a66efee 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java @@ -183,7 +183,7 @@ private void buttonPressed(String button) { if (edited) { ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.output(Localization.lang("Updated entry with info from DOI")); panel.updateEntryEditorIfShowing(); panel.markBaseChanged(); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java index add2f755d703..c3437ccf9871 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java @@ -279,7 +279,7 @@ else if (autoCompFF.isSelected()) { (oldAutoCompFModeAbbr != firstNameModeAbbr.isSelected()) || (oldAutoCompFModeFull != firstNameModeFull.isSelected())) { for (BasePanel panel : frame.getBasePanelList()) { - panel.entryEditors.clear(); + panel.getEntryEditors().clear(); } } } diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java index c6ba1c5b77c7..a3aa069596ab 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java @@ -631,8 +631,8 @@ public void actionPerformed(ActionEvent e) { final HashMap map = new HashMap<>(); // first element (#) not inside tableRows - for (int i = 1; i < panel.mainTable.getColumnCount(); i++) { - String name = panel.mainTable.getColumnName(i); + for (int i = 1; i < panel.getMainTable().getColumnCount(); i++) { + String name = panel.getMainTable().getColumnName(i); if ((name != null) && !name.isEmpty()) { map.put(name.toLowerCase(), i); } @@ -664,11 +664,11 @@ public void actionPerformed(ActionEvent e) { if (panel == null) { return; } - TableColumnModel colMod = panel.mainTable.getColumnModel(); + TableColumnModel colMod = panel.getMainTable().getColumnModel(); colSetup.setValueAt(String.valueOf(colMod.getColumn(0).getWidth()), 0, 1); for (int i = 1; i < colMod.getColumnCount(); i++) { try { - String name = panel.mainTable.getColumnName(i).toLowerCase(); + String name = panel.getMainTable().getColumnName(i).toLowerCase(); int width = colMod.getColumn(i).getWidth(); if ((i <= tableRows.size()) && ((String) colSetup.getValueAt(i, 0)).equalsIgnoreCase(name)) { colSetup.setValueAt(String.valueOf(width), i, 1); diff --git a/src/main/java/net/sf/jabref/gui/search/SearchBar.java b/src/main/java/net/sf/jabref/gui/search/SearchBar.java index d6f68297b826..11aa5ae42508 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchBar.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchBar.java @@ -245,9 +245,9 @@ public void keyReleased(KeyEvent e) { private void endSearch() { // first focus request is necessary so that the UI stays nice - basePanel.mainTable.requestFocus(); + basePanel.getMainTable().requestFocus(); clearSearch(); - basePanel.mainTable.requestFocus(); + basePanel.getMainTable().requestFocus(); } /** @@ -281,7 +281,7 @@ private void clearSearch() { this.currentResults.setText(""); - basePanel.mainTable.getTableModel().updateSearchState(MainTableDataModel.DisplayOption.DISABLED); + basePanel.getMainTable().getTableModel().updateSearchState(MainTableDataModel.DisplayOption.DISABLED); globalSearch.setEnabled(false); openCurrentResultsInDialog.setEnabled(false); @@ -324,7 +324,7 @@ private void informUserAboutInvalidSearchQuery() { globalSearch.setEnabled(false); openCurrentResultsInDialog.setEnabled(false); - basePanel.mainTable.getTableModel().updateSearchState(MainTableDataModel.DisplayOption.DISABLED); + basePanel.getMainTable().getTableModel().updateSearchState(MainTableDataModel.DisplayOption.DISABLED); searchIcon.setIcon(IconTheme.JabRefIcon.SEARCH.getSmallIcon().createWithNewColor(NO_RESULTS_COLOR)); searchIcon.setToolTipText(Localization.lang("Search failed: illegal search expression")); diff --git a/src/main/java/net/sf/jabref/gui/search/SearchWorker.java b/src/main/java/net/sf/jabref/gui/search/SearchWorker.java index 3d4b2bb07552..355627dcedb2 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchWorker.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchWorker.java @@ -76,15 +76,15 @@ private void updateUIWithSearchResult(List matchedEntries) { entry.setSearchHit(true); } - basePanel.mainTable.getTableModel().updateSearchState(MainTableDataModel.DisplayOption.DISABLED); + basePanel.getMainTable().getTableModel().updateSearchState(MainTableDataModel.DisplayOption.DISABLED); // Show the result in the chosen way: switch (mode) { case FLOAT: - basePanel.mainTable.getTableModel().updateSearchState(MainTableDataModel.DisplayOption.FLOAT); + basePanel.getMainTable().getTableModel().updateSearchState(MainTableDataModel.DisplayOption.FLOAT); break; case FILTER: - basePanel.mainTable.getTableModel().updateSearchState(MainTableDataModel.DisplayOption.FILTER); + basePanel.getMainTable().getTableModel().updateSearchState(MainTableDataModel.DisplayOption.FILTER); break; default: break; @@ -92,8 +92,8 @@ private void updateUIWithSearchResult(List matchedEntries) { // select first match (i.e., row) if there is any int hits = matchedEntries.size(); - if ((hits > 0) && (basePanel.mainTable.getRowCount() > 0)) { - basePanel.mainTable.setSelected(0); + if ((hits > 0) && (basePanel.getMainTable().getRowCount() > 0)) { + basePanel.getMainTable().setSelected(0); } basePanel.getSearchBar().updateResults(hits, searchQuery.getDescription(), searchQuery.isGrammarBasedSearch()); diff --git a/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java b/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java index 11ee6b3cb29f..dbbcad678882 100644 --- a/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java +++ b/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java @@ -86,7 +86,7 @@ public void run() { EntryMarker.markEntry(be, level + 1, false, ce); } ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } } diff --git a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java index df5e356c70b3..bed6161798f6 100644 --- a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java @@ -192,7 +192,7 @@ private static void mergeFromBibtex(JabRefFrame frame, BasePanel panel, ParserRe } ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); } } diff --git a/src/main/java/net/sf/jabref/importer/EntryFromFileCreatorManager.java b/src/main/java/net/sf/jabref/importer/EntryFromFileCreatorManager.java index 05c587451010..342bd424379c 100644 --- a/src/main/java/net/sf/jabref/importer/EntryFromFileCreatorManager.java +++ b/src/main/java/net/sf/jabref/importer/EntryFromFileCreatorManager.java @@ -180,7 +180,7 @@ public int addEntriesFromFiles(List files, if ((count > 0) && (panel != null)) { ce.end(); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); } return count; diff --git a/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java b/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java index 557658ebd0e6..485cc674e927 100644 --- a/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java +++ b/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java @@ -56,7 +56,7 @@ protected Optional createBibtexEntry(File pdfFile) { return Optional.empty(); } - PdfImporter pi = new PdfImporter(JabRefGUI.getMainFrame(), JabRefGUI.getMainFrame().getCurrentBasePanel(), JabRefGUI.getMainFrame().getCurrentBasePanel().mainTable, -1); + PdfImporter pi = new PdfImporter(JabRefGUI.getMainFrame(), JabRefGUI.getMainFrame().getCurrentBasePanel(), JabRefGUI.getMainFrame().getCurrentBasePanel().getMainTable(), -1); String[] fileNames = {pdfFile.toString()}; ImportPdfFilesResult res = pi.importPdfFiles(fileNames); if (res.getEntries().size() == 1) { diff --git a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java index f002cf204bab..55e03ec6868d 100644 --- a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java +++ b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java @@ -194,7 +194,7 @@ private void makeChanges(BasePanel panel, ParserResult pr, boolean upgradePrefs, if (upgradeDatabase) { // Update file links links in the database: NamedCompound ce = upgradePdfPsToFile(pr.getDatabase(), FileLinksUpgradeWarning.FIELDS_TO_LOOK_FOR); - panel.undoManager.addEdit(ce); + panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); } diff --git a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java index c11a98357ffc..c961bf6730af 100644 --- a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java +++ b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java @@ -282,7 +282,7 @@ private BibEntry createNewEntry() { UpdateField.setAutomaticFields(list, true, true); // Create an UndoableInsertEntry object. - panel.undoManager.addEdit(new UndoableInsertEntry(panel.getDatabase(), be, panel)); + panel.getUndoManager().addEdit(new UndoableInsertEntry(panel.getDatabase(), be, panel)); panel.output(Localization.lang("Added new") + " '" + type.getName().toLowerCase() + "' " + Localization.lang("entry") + "."); diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java index c96592111097..9585bcc13e0c 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldAction.java @@ -67,7 +67,7 @@ public void action() { } ce.end(); if (ce.hasEdits()) { - frame.getCurrentBasePanel().undoManager.addEdit(ce); + frame.getCurrentBasePanel().getUndoManager().addEdit(ce); frame.getCurrentBasePanel().markBaseChanged(); frame.getCurrentBasePanel().updateEntryEditorIfShowing(); String outText; diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java index 070af993b29f..6ad1449b7387 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java @@ -26,7 +26,6 @@ public class SpecialFieldDatabaseChangeListener { private static SpecialFieldDatabaseChangeListener INSTANCE; - public static SpecialFieldDatabaseChangeListener getInstance() { if (SpecialFieldDatabaseChangeListener.INSTANCE == null) { SpecialFieldDatabaseChangeListener.INSTANCE = new SpecialFieldDatabaseChangeListener(); diff --git a/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java b/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java index c4b664c70ac4..3c7da777093c 100644 --- a/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java +++ b/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java @@ -245,6 +245,8 @@ private void importGroupsTree(MetaData metaData, Map entries, rsGroups.getBoolean("case_sensitive"), rsGroups.getBoolean("reg_exp"), GroupHierarchyType.getByNumber(rsGroups.getInt("hierarchical_context"))); break; + default: + break; } } catch (ParseException e) { LOGGER.error(e); From a6769dd81782a0010681fdd14622c1fcc43519fb Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Fri, 3 Jun 2016 12:10:28 +0200 Subject: [PATCH 130/268] Remove umlauts from word export title #421 (#1465) * Split MsBib functionality into Converter classes * Put all mappings inside a mapping class * Fixes #421 Remove LaTeX commands from all BibTeX fields when exporting to Word Bibliography --- CHANGELOG.md | 1 + .../sf/jabref/exporter/MSBibExportFormat.java | 2 +- .../format/LatexToUnicodeFormatter.java | 1 + .../net/sf/jabref/logic/mods/PageNumbers.java | 18 +- .../jabref/logic/msbib/BibTeXConverter.java | 112 ++ .../sf/jabref/logic/msbib/MSBibConverter.java | 143 +++ .../sf/jabref/logic/msbib/MSBibDatabase.java | 57 +- .../net/sf/jabref/logic/msbib/MSBibEntry.java | 1052 +++-------------- .../sf/jabref/logic/msbib/MSBibEntryType.java | 30 + .../sf/jabref/logic/msbib/MSBibMapping.java | 130 ++ .../exporter/MSBibExportFormatTestFiles.java | 5 +- .../exporter/MsBibExportFormatTest.java | 25 - .../fileformat/MsBibImporterTestfiles.java | 2 +- .../NormalizePagesFormatterTest.java | 3 +- .../exporter/MsBibExportFormatUmlauts.bib | 3 + .../exporter/MsBibExportFormatUmlauts.xml | 10 + .../net/sf/jabref/exporter/MsBibLCID.bib | 4 + .../net/sf/jabref/exporter/MsBibLCID.xml | 9 + .../resources/net/sf/jabref/exporter/test.xml | 601 ---------- .../fileformat/MsBibImporterTest1.xml | 1 - .../fileformat/MsBibImporterTest2.bib | 2 + .../fileformat/MsBibImporterTest2.xml | 4 +- .../fileformat/MsBibImporterTest3.xml | 3 +- .../fileformat/MsBibImporterTest4.xml | 3 +- .../fileformat/MsBibImporterTest5.xml | 3 +- .../fileformat/MsBibImporterTest6.xml | 3 +- .../jabref/importer/fileformat/MsBibLCID.bib | 4 + .../jabref/importer/fileformat/MsBibLCID.xml | 7 + 28 files changed, 644 insertions(+), 1594 deletions(-) create mode 100644 src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java create mode 100644 src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java create mode 100644 src/main/java/net/sf/jabref/logic/msbib/MSBibEntryType.java create mode 100644 src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.xml create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibLCID.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibLCID.xml delete mode 100644 src/test/resources/net/sf/jabref/exporter/test.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 270a522dc4fe..1c649f8abffb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -104,6 +104,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1457](https://github.com/JabRef/jabref/issues/1457): Support multiple words inside LaTeX commands to RTF export - Entries retain their groupmembership when undoing their cut/deletion - Fixed [#1450](https://github.com/JabRef/jabref/issues/1450): EntryEditor is restored in the correct size after preference changes +- Fixed [#421](https://github.com/JabRef/jabref/issues/421): Remove LaTeX commands from all BibTeX fields when exporting to Word Bibliography ### Removed - Removed possibility to export entries/databases to an `.sql` file, as the logic cannot easily use the correct escape logic diff --git a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java b/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java index 3ff579d185b4..4f4c265f6a5b 100644 --- a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java @@ -58,7 +58,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String try (VerifyingWriter ps = session.getWriter()) { try { - DOMSource source = new DOMSource(msBibDatabase.getDOMrepresentation()); + DOMSource source = new DOMSource(msBibDatabase.getDOM()); StreamResult result = new StreamResult(ps); Transformer trans = TransformerFactory.newInstance().newTransformer(); trans.setOutputProperty(OutputKeys.INDENT, "yes"); diff --git a/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java b/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java index 99c56812c976..abe2818fc414 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java @@ -48,6 +48,7 @@ public String format(String inField) { return ""; } int i; + // TODO: document what does this do String field = inField.replaceAll("&|\\\\&", "&").replaceAll("[\\n]{1,}", "

    ").replace("\\$", "$") // Replace \$ with $ .replaceAll("\\$([^\\$]*)\\$", "\\{$1\\}"); diff --git a/src/main/java/net/sf/jabref/logic/mods/PageNumbers.java b/src/main/java/net/sf/jabref/logic/mods/PageNumbers.java index 912a0f7e18de..35e9e1aad4a8 100644 --- a/src/main/java/net/sf/jabref/logic/mods/PageNumbers.java +++ b/src/main/java/net/sf/jabref/logic/mods/PageNumbers.java @@ -22,30 +22,24 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; -/** - * @author Michael Wrighton - * @author S M Mahbub Murshed - * - */ public class PageNumbers { - private String freeform; private int start; private int end; private static final Pattern PAGE_PATTERN = Pattern.compile("\\s*(\\d+)\\s*-{1,2}\\s*(\\d+)\\s*"); - public PageNumbers(String s) { - parsePageNums(s); + public PageNumbers(String pages) { + parsePageNums(pages); } - private void parsePageNums(String numberString) { - Matcher matcher = PAGE_PATTERN.matcher(numberString); + private void parsePageNums(String pages) { + Matcher matcher = PAGE_PATTERN.matcher(pages); if (matcher.matches()) { start = Integer.parseInt(matcher.group(1)); end = Integer.parseInt(matcher.group(2)); } else { - freeform = numberString; + freeform = pages; } } @@ -75,7 +69,7 @@ public String toString(String separator) { @Override public String toString() { - return toString("--"); + return toString("-"); } } diff --git a/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java b/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java new file mode 100644 index 000000000000..7965ac433752 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java @@ -0,0 +1,112 @@ +package net.sf.jabref.logic.msbib; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import net.sf.jabref.importer.fileformat.ImportFormat; +import net.sf.jabref.logic.mods.PersonName; +import net.sf.jabref.model.entry.BibEntry; + +public class BibTeXConverter { + private static final String MSBIB_PREFIX = "msbib-"; + + public static BibEntry convert(MSBibEntry entry) { + BibEntry result; + Map fieldValues = new HashMap<>(); + + if (entry.getCiteKey() == null) { + result = new BibEntry(ImportFormat.DEFAULT_BIBTEXENTRY_ID, MSBibMapping.getBibTeXEntryType(entry.getType())); + } else { + // TODO: the cite key should not be the ID?! + // id assumes an existing database so don't + result = new BibEntry(entry.getCiteKey(), MSBibMapping.getBibTeXEntryType(entry.getType())); + } + + // add String fields + for (Map.Entry field : entry.fields.entrySet()) { + String msField = field.getKey(); + String value = field.getValue(); + + if (value != null && MSBibMapping.getBibTeXField(msField) != null) { + fieldValues.put(MSBibMapping.getBibTeXField(msField), value); + } + } + + // Value must be converted + if (fieldValues.containsKey("language")) { + int lcid = Integer.valueOf(fieldValues.get("language")); + fieldValues.put("language", MSBibMapping.getLanguage(lcid)); + } + + addAuthor(fieldValues, "author", entry.authors); + addAuthor(fieldValues, MSBIB_PREFIX + "bookauthor", entry.bookAuthors); + addAuthor(fieldValues, "editor", entry.editors); + addAuthor(fieldValues, MSBIB_PREFIX + "translator", entry.translators); + addAuthor(fieldValues, MSBIB_PREFIX + "producername", entry.producerNames); + addAuthor(fieldValues, MSBIB_PREFIX + "composer", entry.composers); + addAuthor(fieldValues, MSBIB_PREFIX + "conductor", entry.conductors); + addAuthor(fieldValues, MSBIB_PREFIX + "performer", entry.performers); + addAuthor(fieldValues, MSBIB_PREFIX + "writer", entry.writers); + addAuthor(fieldValues, MSBIB_PREFIX + "director", entry.directors); + addAuthor(fieldValues, MSBIB_PREFIX + "compiler", entry.compilers); + addAuthor(fieldValues, MSBIB_PREFIX + "interviewer", entry.interviewers); + addAuthor(fieldValues, MSBIB_PREFIX + "interviewee", entry.interviewees); + addAuthor(fieldValues, MSBIB_PREFIX + "inventor", entry.inventors); + addAuthor(fieldValues, MSBIB_PREFIX + "counsel", entry.counsels); + + if (entry.pages != null) { + fieldValues.put("pages", entry.pages.toString("--")); + } + + parseStandardNumber(entry.standardNumber, fieldValues); + + if (entry.address != null) { + fieldValues.put("address", entry.address); + } + // TODO: ConferenceName is saved as booktitle when converting from MSBIB to BibTeX + if (entry.conferenceName != null) { + fieldValues.put("organization", entry.conferenceName); + } + + if (entry.dateAccessed != null) { + fieldValues.put(MSBIB_PREFIX + "accessed", entry.dateAccessed); + } + + // set all fields + result.setField(fieldValues); + + return result; + } + + private static void addAuthor(Map map, String type, List authors) { + if (authors == null) { + return; + } + String allAuthors = authors.stream().map(PersonName::getFullname).collect(Collectors.joining(" and ")); + + map.put(type, allAuthors); + } + + private static void parseSingleStandardNumber(String type, String bibtype, String standardNum, Map map) { + Pattern pattern = Pattern.compile(':' + type + ":(.[^:]+)"); + Matcher matcher = pattern.matcher(standardNum); + if (matcher.matches()) { + map.put(bibtype, matcher.group(1)); + } + } + + private static void parseStandardNumber(String standardNum, Map map) { + if (standardNum == null) { + return; + } + parseSingleStandardNumber("ISBN", "isbn", standardNum, map); + parseSingleStandardNumber("ISSN", "issn", standardNum, map); + parseSingleStandardNumber("LCCN", "lccn", standardNum, map); + parseSingleStandardNumber("MRN", "mrnumber", standardNum, map); + parseSingleStandardNumber("DOI", "doi", standardNum, map); + } +} diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java new file mode 100644 index 000000000000..9579d748debe --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java @@ -0,0 +1,143 @@ +package net.sf.jabref.logic.msbib; + +import java.util.ArrayList; +import java.util.List; + +import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; +import net.sf.jabref.logic.layout.format.RemoveBrackets; +import net.sf.jabref.logic.mods.PageNumbers; +import net.sf.jabref.logic.mods.PersonName; +import net.sf.jabref.model.entry.BibEntry; + +public class MSBibConverter { + private static final String MSBIB_PREFIX = "msbib-"; + private static final String BIBTEX_PREFIX = "BIBTEX_"; + + public static MSBibEntry convert(BibEntry entry) { + MSBibEntry result = new MSBibEntry(); + + // memorize original type + result.fields.put(BIBTEX_PREFIX + "Entry", entry.getType()); + // define new type + String msbibType = result.fields.put("SourceType", MSBibMapping.getMSBibEntryType(entry.getType()).name()); + + for (String field : entry.getFieldNames()) { + // clean field + String unicodeField = removeLaTeX(entry.getField(field)); + + if (MSBibMapping.getMSBibField(field) != null) { + result.fields.put(MSBibMapping.getMSBibField(field), unicodeField); + } + } + + // Duplicate: also added as BookTitle + if (entry.hasField("booktitle")) { + result.conferenceName = entry.getField("booktitle"); + } + + if (entry.hasField("pages")) { + result.pages = new PageNumbers(entry.getField("pages")); + } + + if (entry.hasField(MSBIB_PREFIX + "accessed")) { + result.dateAccessed = entry.getField(MSBIB_PREFIX + "accessed"); + } + + // TODO: currently this can never happen + if ("SoundRecording".equals(msbibType) && (entry.hasField("title"))) { + result.albumTitle = entry.getField("title"); + } + + // TODO: currently this can never happen + if ("Interview".equals(msbibType) && (entry.hasField("title"))) { + result.broadcastTitle = entry.getField("title"); + } + + // Value must be converted + if (entry.hasField("language")) { + result.fields.put("LCID", String.valueOf(MSBibMapping.getLCID(entry.getField("language")))); + } + + result.standardNumber = ""; + if (entry.hasField("isbn")) { + result.standardNumber += " ISBN: " + entry.getField("isbn"); + } + if (entry.hasField("issn")) { + result.standardNumber += " ISSN: " + entry.getField("issn"); + } + if (entry.hasField("lccn")) { + result.standardNumber += " LCCN: " + entry.getField("lccn"); + } + if (entry.hasField("mrnumber")) { + result.standardNumber += " MRN: " + entry.getField("mrnumber"); + } + if (entry.hasField("doi")) { + result.standardNumber += " DOI: " + entry.getField("doi"); + } + if (result.standardNumber.isEmpty()) { + result.standardNumber = null; + } + + if (entry.hasField("address")) { + result.address = entry.getField("address"); + } + + if (entry.hasField("type")) { + result.thesisType = entry.getField("type"); + } else { + if ("techreport".equalsIgnoreCase(entry.getType())) { + result.thesisType = "Tech. rep."; + } else if ("mastersthesis".equalsIgnoreCase(entry.getType())) { + result.thesisType = "Master's thesis"; + } else if ("phdthesis".equalsIgnoreCase(entry.getType())) { + result.thesisType = "Ph.D. dissertation"; + } else if ("unpublished".equalsIgnoreCase(entry.getType())) { + result.thesisType = "unpublished"; + } + } + + // TODO: currently this can never happen + if (("InternetSite".equals(msbibType) || "DocumentFromInternetSite".equals(msbibType)) + && (entry.hasField("title"))) { + result.internetSiteTitle = entry.getField("title"); + } + + // TODO: currently only Misc can happen + if (("ElectronicSource".equals(msbibType) || "Art".equals(msbibType) || "Misc".equals(msbibType)) + && (entry.hasField("title"))) { + result.publicationTitle = entry.getField("title"); + } + + if (entry.hasField("author")) { + result.authors = getAuthors(entry.getField("author")); + } + if (entry.hasField("editor")) { + result.editors = getAuthors(entry.getField("editor")); + } + + return result; + } + + private static List getAuthors(String authors) { + List result = new ArrayList<>(); + + // TODO: case-insensitive?! + if (authors.contains(" and ")) { + String[] names = authors.split(" and "); + for (String name : names) { + result.add(new PersonName(name)); + } + } else { + result.add(new PersonName(authors)); + } + return result; + } + + private static String removeLaTeX(String text) { + // TODO: just use latex free version everywhere in the future + String result = new RemoveBrackets().format(text); + result = new LatexToUnicodeFormatter().format(result); + + return result; + } +} diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java index 91bfb3e90a14..790026f36d25 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibDatabase.java @@ -47,13 +47,16 @@ public class MSBibDatabase { private static final Log LOGGER = LogFactory.getLog(MSBibDatabase.class); + public static final String NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography"; + public static final String PREFIX = "b:"; + private Set entries; public MSBibDatabase() { - // maybe make this sorted later... entries = new HashSet<>(); } + // TODO: why an additonal entry list? entries are included inside database! public MSBibDatabase(BibDatabase database, List entries) { if (entries == null) { addEntries(database.getEntries()); @@ -66,30 +69,28 @@ public List importEntries(BufferedReader reader) { entries = new HashSet<>(); Document inputDocument; try { - DocumentBuilder documentBuilder = DocumentBuilderFactory. - newInstance(). - newDocumentBuilder(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + DocumentBuilder documentBuilder = factory.newDocumentBuilder(); inputDocument = documentBuilder.parse(new InputSource(reader)); } catch (ParserConfigurationException | SAXException | IOException e) { LOGGER.warn("Could not parse document", e); return Collections.emptyList(); } - String bcol = "b:"; - NodeList rootList = inputDocument.getElementsByTagName("b:Sources"); + NodeList rootList = inputDocument.getElementsByTagNameNS("*", "Sources"); if (rootList.getLength() == 0) { - rootList = inputDocument.getElementsByTagName("Sources"); - bcol = ""; + rootList = inputDocument.getElementsByTagNameNS("*", "Sources"); } List bibitems = new ArrayList<>(); if (rootList.getLength() == 0) { return bibitems; } - NodeList sourceList = ((Element) rootList.item(0)).getElementsByTagName(bcol + "Source"); + NodeList sourceList = ((Element) rootList.item(0)).getElementsByTagNameNS("*", "Source"); for (int i = 0; i < sourceList.getLength(); i++) { - MSBibEntry entry = new MSBibEntry((Element) sourceList.item(i), bcol); + MSBibEntry entry = new MSBibEntry((Element) sourceList.item(i)); entries.add(entry); - bibitems.add(entry.getBibtexRepresentation()); + bibitems.add(BibTeXConverter.convert(entry)); } return bibitems; @@ -98,32 +99,34 @@ public List importEntries(BufferedReader reader) { private void addEntries(List entriesToAdd) { entries = new HashSet<>(); for (BibEntry entry : entriesToAdd) { - MSBibEntry newMods = new MSBibEntry(entry); + MSBibEntry newMods = MSBibConverter.convert(entry); entries.add(newMods); } } - public Document getDOMrepresentation() { - Document result = null; + public Document getDOM() { + Document document = null; try { - DocumentBuilder documentBuilder = DocumentBuilderFactory. - newInstance(). - newDocumentBuilder(); - result = documentBuilder.newDocument(); - Element msbibCollection = result.createElement("b:Sources"); - msbibCollection.setAttribute("SelectedStyle", ""); - msbibCollection.setAttribute("xmlns", "http://schemas.openxmlformats.org/officeDocument/2006/bibliography"); - msbibCollection.setAttribute("xmlns:b", "http://schemas.openxmlformats.org/officeDocument/2006/bibliography"); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + DocumentBuilder documentBuilder = factory.newDocumentBuilder(); + document = documentBuilder.newDocument(); + + Element rootNode = document.createElementNS(NAMESPACE, PREFIX + "Sources"); + rootNode.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", NAMESPACE); + rootNode.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" + PREFIX.substring(0, PREFIX.length() - 1), NAMESPACE); + rootNode.setAttribute("SelectedStyle", ""); for (MSBibEntry entry : entries) { - Node node = entry.getDOMrepresentation(result); - msbibCollection.appendChild(node); + Node node = entry.getDOM(document); + rootNode.appendChild(node); } - result.appendChild(msbibCollection); + document.appendChild(rootNode); } catch (ParserConfigurationException e) { - LOGGER.warn("Could not build document", e); + LOGGER.warn("Could not build XML document", e); } - return result; + + return document; } } diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java index 26766f2b3669..0bce537df150 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntry.java @@ -21,130 +21,54 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; -import net.sf.jabref.importer.fileformat.ImportFormat; - -import net.sf.jabref.logic.layout.format.RemoveBrackets; import net.sf.jabref.logic.mods.PageNumbers; import net.sf.jabref.logic.mods.PersonName; import net.sf.jabref.logic.util.strings.StringUtil; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.BibtexEntryTypes; -import net.sf.jabref.model.entry.EntryType; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** - * Date: May 15, 2007; May 03, 2007 - *

    - * History - * May 03, 2007 - Added export functionality - * May 15, 2007 - Added import functionality - * May 16, 2007 - Changed all interger entries to strings, - * except LCID which must be an integer. - * To avoid exception during integer parsing - * the exception is caught and LCID is set to zero. - * Jan 06, 2012 - Changed the XML element ConferenceName to present - * the Booktitle instead of the organization field content + * MSBib entry representation * - * @author S M Mahbub Murshed (udvranto@yahoo.com) - * @version 2.0.0 * @see ms office 2007 bibliography format compared to bibtex * @see deciphering ms office 2007 bibliography format - * See http://www.ecma-international.org/publications/standards/Ecma-376.htm + * @see ECMA Standard */ class MSBibEntry { - - private String sourceType = "Misc"; - private String bibTexEntry; - - private String tag; - private static final String GUID = null; - private int LCID = -1; - - private List authors; - private List bookAuthors; - private List editors; - private List translators; - private List producerNames; - private List composers; - private List conductors; - private List performers; - private List writers; - private List directors; - private List compilers; - private List interviewers; - private List interviewees; - private List inventors; - private List counsels; - - private String title; - private String year; - private String month; - private String day; - - private String shortTitle; - private String comments; - - private PageNumbers pages; - private String volume; - private String numberOfVolumes; - private String edition; - private String standardNumber; - private String publisher; - - private String address; - private String bookTitle; - private String chapterNumber; - private String journalName; - private String issue; - private String periodicalTitle; - private String conferenceName; - private String department; - private String institution; - private String thesisType; - private String internetSiteTitle; - private String dateAccessed; - private String doi; - private String url; - private String productionCompany; - private String publicationTitle; - private String medium; - private String albumTitle; - private String recordingNumber; - private String theater; - private String distributor; - private String broadcastTitle; - private String broadcaster; - private String station; - private String type; - private String patentNumber; - private String court; - private String reporter; - private String caseNumber; - private String abbreviatedCaseNumber; - private String bibTexSeries; - private String bibTexAbstract; - private String bibTexKeyWords; - private String bibTexCrossRef; - private String bibTex_HowPublished; - private String bibTexAffiliation; - private String bibTexContents; - private String bibTexCopyright; - private String bibTexPrice; - private String bibTexSize; - - /* SM 2010.10 intype, paper support */ - private String bibTexInType; - private String bibTexPaper; - - private static final String BIBTEX = "BIBTEX_"; - private static final String MSBIB = "msbib-"; - - private static final String B_COLON = "b:"; + // MSBib fields and values + public Map fields = new HashMap<>(); + + public List authors; + public List bookAuthors; + public List editors; + public List translators; + public List producerNames; + public List composers; + public List conductors; + public List performers; + public List writers; + public List directors; + public List compilers; + public List interviewers; + public List interviewees; + public List inventors; + public List counsels; + + public PageNumbers pages; + + public String standardNumber; + public String address; + public String conferenceName; + public String thesisType; + public String internetSiteTitle; + public String dateAccessed; + public String publicationTitle; + public String albumTitle; + public String broadcastTitle; // reduced subset, supports only "CITY , STATE, COUNTRY" // \b(\w+)\s?[,]?\s?(\w+)\s?[,]?\s?(\w+)\b @@ -156,69 +80,55 @@ class MSBibEntry { // (\d{1,2})\s?[.,-/]\s?(\d{1,2})\s?[.,-/]\s?(\d{2,4}) // 1-2 DIGITS SPACE SEPERATOR SPACE 1-2 DIGITS SPACE SEPERATOR SPACE 2-4 DIGITS // tested using http://www.javaregex.com/test.html - private static final Pattern DATE_PATTERN = Pattern - .compile("(\\d{1,2})\\s*[.,-/]\\s*(\\d{1,2})\\s*[.,-/]\\s*(\\d{2,4})"); + private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{1,2})\\s*[.,-/]\\s*(\\d{1,2})\\s*[.,-/]\\s*(\\d{2,4})"); + public MSBibEntry() { - public MSBibEntry(BibEntry bibtex) { - populateFromBibtex(bibtex); } - public MSBibEntry(Element entry, String bcol) { - populateFromXml(entry, bcol); + public MSBibEntry(Element entry) { + populateFromXml(entry); } - private String getFromXml(String name, Element entry) { + public String getType() { + return fields.get("SourceType"); + } + + public String getCiteKey() { + return fields.get("Tag"); + } + + private String getXmlElementTextContent(String name, Element entry) { String value = null; - NodeList nodeLst = entry.getElementsByTagName(name); + NodeList nodeLst = entry.getElementsByTagNameNS("*", name); if (nodeLst.getLength() > 0) { value = nodeLst.item(0).getTextContent(); } return value; } - private void populateFromXml(Element entry, String bcol) { - String temp; - - sourceType = getFromXml(bcol + "SourceType", entry); + private void populateFromXml(Element entry) { + for (int i = 0; i < entry.getChildNodes().getLength(); i++) { + Node node = entry.getChildNodes().item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + String key = node.getLocalName(); + String value = node.getTextContent(); - tag = getFromXml(bcol + "Tag", entry); - - temp = getFromXml(bcol + "LCID", entry); - if (temp != null) { - try { - LCID = Integer.parseInt(temp); - } catch (NumberFormatException e) { - LCID = -1; + fields.put(key, value); } } - title = getFromXml(bcol + "Title", entry); - year = getFromXml(bcol + "Year", entry); - month = getFromXml(bcol + "Month", entry); - day = getFromXml(bcol + "Day", entry); - - shortTitle = getFromXml(bcol + "ShortTitle", entry); - comments = getFromXml(bcol + "Comments", entry); - - temp = getFromXml(bcol + "Pages", entry); + String temp = getXmlElementTextContent("Pages", entry); if (temp != null) { pages = new PageNumbers(temp); } - volume = getFromXml(bcol + "Volume", entry); - - numberOfVolumes = getFromXml(bcol + "NumberVolumes", entry); - - edition = getFromXml(bcol + "Edition", entry); - - standardNumber = getFromXml(bcol + "StandardNumber", entry); + standardNumber = getXmlElementTextContent("StandardNumber", entry); + conferenceName = getXmlElementTextContent("ConferenceName", entry); - publisher = getFromXml(bcol + "Publisher", entry); - - String city = getFromXml(bcol + "City", entry); - String state = getFromXml(bcol + "StateProvince", entry); - String country = getFromXml(bcol + "CountryRegion", entry); + String city = getXmlElementTextContent("City", entry); + String state = getXmlElementTextContent("StateProvince", entry); + String country = getXmlElementTextContent("CountryRegion", entry); StringBuilder addressBuffer = new StringBuilder(); if (city != null) { addressBuffer.append(city).append(", "); @@ -234,25 +144,10 @@ private void populateFromXml(Element entry, String bcol) { address = null; } - bookTitle = getFromXml(bcol + "BookTitle", entry); - - chapterNumber = getFromXml(bcol + "ChapterNumber", entry); - - journalName = getFromXml(bcol + "JournalName", entry); - - issue = getFromXml(bcol + "Issue", entry); - - periodicalTitle = getFromXml(bcol + "PeriodicalTitle", entry); - - conferenceName = getFromXml(bcol + "ConferenceName", entry); - department = getFromXml(bcol + "Department", entry); - institution = getFromXml(bcol + "Institution", entry); - - thesisType = getFromXml(bcol + "ThesisType", entry); - internetSiteTitle = getFromXml(bcol + "InternetSiteTitle", entry); - String month = getFromXml(bcol + "MonthAccessed", entry); - String day = getFromXml(bcol + "DayAccessed", entry); - String year = getFromXml(bcol + "YearAccessed", entry); + internetSiteTitle = getXmlElementTextContent("InternetSiteTitle", entry); + String month = getXmlElementTextContent("MonthAccessed", entry); + String day = getXmlElementTextContent("DayAccessed", entry); + String year = getXmlElementTextContent("YearAccessed", entry); dateAccessed = ""; if (month != null) { dateAccessed += month + ' '; @@ -268,311 +163,50 @@ private void populateFromXml(Element entry, String bcol) { dateAccessed = null; } - doi = getFromXml(bcol + "DOI", entry); - url = getFromXml(bcol + "URL", entry); - productionCompany = getFromXml(bcol + "ProductionCompany", entry); - - publicationTitle = getFromXml(bcol + "PublicationTitle", entry); - medium = getFromXml(bcol + "Medium", entry); - albumTitle = getFromXml(bcol + "AlbumTitle", entry); - recordingNumber = getFromXml(bcol + "RecordingNumber", entry); - theater = getFromXml(bcol + "Theater", entry); - distributor = getFromXml(bcol + "Distributor", entry); - broadcastTitle = getFromXml(bcol + "BroadcastTitle", entry); - broadcaster = getFromXml(bcol + "Broadcaster", entry); - station = getFromXml(bcol + "Station", entry); - type = getFromXml(bcol + "Type", entry); - patentNumber = getFromXml(bcol + "PatentNumber", entry); - court = getFromXml(bcol + "Court", entry); - reporter = getFromXml(bcol + "Reporter", entry); - caseNumber = getFromXml(bcol + "CaseNumber", entry); - abbreviatedCaseNumber = getFromXml(bcol + "AbbreviatedCaseNumber", entry); - bibTexSeries = getFromXml(bcol + BIBTEX + "Series", entry); - bibTexAbstract = getFromXml(bcol + BIBTEX + "Abstract", entry); - bibTexKeyWords = getFromXml(bcol + BIBTEX + "KeyWords", entry); - bibTexCrossRef = getFromXml(bcol + BIBTEX + "CrossRef", entry); - bibTex_HowPublished = getFromXml(bcol + BIBTEX + "HowPublished", entry); - bibTexAffiliation = getFromXml(bcol + BIBTEX + "Affiliation", entry); - bibTexContents = getFromXml(bcol + BIBTEX + "Contents", entry); - bibTexCopyright = getFromXml(bcol + BIBTEX + "Copyright", entry); - bibTexPrice = getFromXml(bcol + BIBTEX + "Price", entry); - bibTexSize = getFromXml(bcol + BIBTEX + "Size", entry); - - NodeList nodeLst = entry.getElementsByTagName(bcol + "Author"); + NodeList nodeLst = entry.getElementsByTagNameNS("*", "Author"); if (nodeLst.getLength() > 0) { - getAuthors((Element) nodeLst.item(0), bcol); - } - } - - private void populateFromBibtex(BibEntry bibtex) { - - sourceType = getMSBibSourceType(bibtex); - - if (bibtex.hasField(BibEntry.KEY_FIELD)) { - tag = bibtex.getCiteKey(); - } - - if (bibtex.hasField("language")) { - LCID = getLCID(bibtex.getField("language")); - } - - if (bibtex.hasField("title")) { - String temp = bibtex.getField("title"); - // TODO: remove LaTex syntax - title = new RemoveBrackets().format(temp); - } - if (bibtex.hasField("year")) { - year = bibtex.getField("year"); - } - if (bibtex.hasField("month")) { - month = bibtex.getField("month"); - } - if (bibtex.hasField(MSBIB + "day")) { - day = bibtex.getField(MSBIB + "day"); - } - - if (bibtex.hasField(MSBIB + "shorttitle")) { - shortTitle = bibtex.getField(MSBIB + "shorttitle"); - } - if (bibtex.hasField("note")) { - comments = bibtex.getField("note"); - } - - if (bibtex.hasField("pages")) { - pages = new PageNumbers(bibtex.getField("pages")); - } - - if (bibtex.hasField("volume")) { - volume = bibtex.getField("volume"); - } - - if (bibtex.hasField(MSBIB + "numberofvolume")) { - numberOfVolumes = bibtex.getField(MSBIB + "numberofvolume"); - } - - if (bibtex.hasField("edition")) { - edition = bibtex.getField("edition"); - } - - standardNumber = ""; - if (bibtex.hasField("isbn")) { - standardNumber += " ISBN: " + bibtex.getField("isbn"); /* SM: 2010.10: lower case */ - } - if (bibtex.hasField("issn")) { - standardNumber += " ISSN: " + bibtex.getField("issn"); /* SM: 2010.10: lower case */ - } - if (bibtex.hasField("lccn")) { - standardNumber += " LCCN: " + bibtex.getField("lccn"); /* SM: 2010.10: lower case */ - } - if (bibtex.hasField("mrnumber")) { - standardNumber += " MRN: " + bibtex.getField("mrnumber"); - } - /* SM: 2010.10 begin DOI support */ - if (bibtex.hasField("doi")) { - standardNumber += " DOI: " + bibtex.getField("doi"); - } - /* SM: 2010.10 end DOI support */ - if (standardNumber.isEmpty()) { - standardNumber = null; - } - - if (bibtex.hasField("publisher")) { - publisher = bibtex.getField("publisher"); - } - - if (bibtex.hasField("address")) { - address = bibtex.getField("address"); - } - - if (bibtex.hasField("booktitle")) { - bookTitle = bibtex.getField("booktitle"); - } - - if (bibtex.hasField("chapter")) { - chapterNumber = bibtex.getField("chapter"); - } - - if (bibtex.hasField("journal")) { - journalName = bibtex.getField("journal"); - } - - if (bibtex.hasField("number")) { - issue = bibtex.getField("number"); - } - - if (bibtex.hasField(MSBIB + "periodical")) { - periodicalTitle = bibtex.getField(MSBIB + "periodical"); - } - - if (bibtex.hasField("booktitle")) { - conferenceName = bibtex.getField("booktitle"); - } - if (bibtex.hasField("school")) { - department = bibtex.getField("school"); - } - if (bibtex.hasField("institution")) { - institution = bibtex.getField("institution"); - } - - /* SM: 2010.10 Modified for default source types */ - if (bibtex.hasField("type")) { - thesisType = bibtex.getField("type"); - } else { - if ("techreport".equalsIgnoreCase(bibtex.getType())) { - thesisType = "Tech. rep."; - } else if ("mastersthesis".equalsIgnoreCase(bibtex.getType())) { - thesisType = "Master's thesis"; - } else if ("phdthesis".equalsIgnoreCase(bibtex.getType())) { - thesisType = "Ph.D. dissertation"; - } else if ("unpublished".equalsIgnoreCase(bibtex.getType())) { - thesisType = "unpublished"; - } - } - - if (("InternetSite".equals(sourceType) || "DocumentFromInternetSite".equals(sourceType)) - && (bibtex.hasField("title"))) { - internetSiteTitle = bibtex.getField("title"); - } - if (bibtex.hasField(MSBIB + "accessed")) { - dateAccessed = bibtex.getField(MSBIB + "accessed"); - } - if (bibtex.hasField("doi")) { - doi = bibtex.getField("doi"); - } - if (bibtex.hasField("url")) { - url = bibtex.getField("url"); + getAuthors((Element) nodeLst.item(0)); } - if (bibtex.hasField(MSBIB + "productioncompany")) { - productionCompany = bibtex.getField(MSBIB + "productioncompany"); - } - - if (("ElectronicSource".equals(sourceType) || "Art".equals(sourceType) || "Misc".equals(sourceType)) - && (bibtex.hasField("title"))) { - publicationTitle = bibtex.getField("title"); - } - if (bibtex.hasField(MSBIB + "medium")) { - medium = bibtex.getField(MSBIB + "medium"); - } - if ("SoundRecording".equals(sourceType) && (bibtex.hasField("title"))) { - albumTitle = bibtex.getField("title"); - } - if (bibtex.hasField(MSBIB + "recordingnumber")) { - recordingNumber = bibtex.getField(MSBIB + "recordingnumber"); - } - if (bibtex.hasField(MSBIB + "theater")) { - theater = bibtex.getField(MSBIB + "theater"); - } - if (bibtex.hasField(MSBIB + "distributor")) { - distributor = bibtex.getField(MSBIB + "distributor"); - } - if ("Interview".equals(sourceType) && (bibtex.hasField("title"))) { - broadcastTitle = bibtex.getField("title"); - } - if (bibtex.hasField(MSBIB + "broadcaster")) { - broadcaster = bibtex.getField(MSBIB + "broadcaster"); - } - if (bibtex.hasField(MSBIB + "station")) { - station = bibtex.getField(MSBIB + "station"); - } - if (bibtex.hasField(MSBIB + "type")) { - type = bibtex.getField(MSBIB + "type"); - } - if (bibtex.hasField(MSBIB + "patentnumber")) { - patentNumber = bibtex.getField(MSBIB + "patentnumber"); - } - if (bibtex.hasField(MSBIB + "court")) { - court = bibtex.getField(MSBIB + "court"); - } - if (bibtex.hasField(MSBIB + "reporter")) { - reporter = bibtex.getField(MSBIB + "reporter"); - } - if (bibtex.hasField(MSBIB + "casenumber")) { - caseNumber = bibtex.getField(MSBIB + "casenumber"); - } - if (bibtex.hasField(MSBIB + "abbreviatedcasenumber")) { - abbreviatedCaseNumber = bibtex.getField(MSBIB + "abbreviatedcasenumber"); - } - - if (bibtex.hasField("series")) { - bibTexSeries = bibtex.getField("series"); - } - if (bibtex.hasField("abstract")) { - bibTexAbstract = bibtex.getField("abstract"); - } - if (bibtex.hasField("keywords")) { - bibTexKeyWords = bibtex.getField("keywords"); - } - if (bibtex.hasField("crossref")) { - bibTexCrossRef = bibtex.getField("crossref"); - } - if (bibtex.hasField("howpublished")) { - bibTex_HowPublished = bibtex.getField("howpublished"); - } - if (bibtex.hasField("affiliation")) { - bibTexAffiliation = bibtex.getField("affiliation"); - } - if (bibtex.hasField("contents")) { - bibTexContents = bibtex.getField("contents"); - } - if (bibtex.hasField("copyright")) { - bibTexCopyright = bibtex.getField("copyright"); - } - if (bibtex.hasField("price")) { - bibTexPrice = bibtex.getField("price"); - } - if (bibtex.hasField("size")) { - bibTexSize = bibtex.getField("size"); - } - - /* SM: 2010.10 end intype, paper support */ - if (bibtex.hasField("intype")) { - bibTexInType = bibtex.getField("intype"); - } - if (bibtex.hasField("paper")) { - bibTexPaper = bibtex.getField("paper"); - } - - if (bibtex.hasField("author")) { - authors = getAuthors(bibtex.getField("author")); - } - if (bibtex.hasField("editor")) { - editors = getAuthors(bibtex.getField("editor")); - } - } - // http://www.microsoft.com/globaldev/reference/lcid-all.mspx - private int getLCID(String language) { - // TODO: add language to LCID mapping - return 0; + private void getAuthors(Element authorsElem) { + authors = getSpecificAuthors("Author", authorsElem); + bookAuthors = getSpecificAuthors("BookAuthor", authorsElem); + editors = getSpecificAuthors("Editor", authorsElem); + translators = getSpecificAuthors("Translator", authorsElem); + producerNames = getSpecificAuthors("ProducerName", authorsElem); + composers = getSpecificAuthors("Composer", authorsElem); + conductors = getSpecificAuthors("Conductor", authorsElem); + performers = getSpecificAuthors("Performer", authorsElem); + writers = getSpecificAuthors("Writer", authorsElem); + directors = getSpecificAuthors("Director", authorsElem); + compilers = getSpecificAuthors("Compiler", authorsElem); + interviewers = getSpecificAuthors("Interviewer", authorsElem); + interviewees = getSpecificAuthors("Interviewee", authorsElem); + inventors = getSpecificAuthors("Inventor", authorsElem); + counsels = getSpecificAuthors("Counsel", authorsElem); } - // http://www.microsoft.com/globaldev/reference/lcid-all.mspx - private String getLanguage(int LCID) { - // TODO: add language to LCID mapping - return "english"; - } - - private List getSpecificAuthors(String type, Element authors, String bcol) { + private List getSpecificAuthors(String type, Element authors) { List result = null; - NodeList nodeLst = authors.getElementsByTagName(bcol + type); + NodeList nodeLst = authors.getElementsByTagNameNS("*", type); if (nodeLst.getLength() <= 0) { return result; } - nodeLst = ((Element) nodeLst.item(0)).getElementsByTagName(bcol + "NameList"); + nodeLst = ((Element) nodeLst.item(0)).getElementsByTagNameNS("*", "NameList"); if (nodeLst.getLength() <= 0) { return result; } - NodeList person = ((Element) nodeLst.item(0)).getElementsByTagName(bcol + "Person"); + NodeList person = ((Element) nodeLst.item(0)).getElementsByTagNameNS("*", "Person"); if (person.getLength() <= 0) { return result; } result = new LinkedList<>(); for (int i = 0; i < person.getLength(); i++) { - NodeList firstName = ((Element) person.item(i)).getElementsByTagName(bcol + "First"); - NodeList lastName = ((Element) person.item(i)).getElementsByTagName(bcol + "Last"); - NodeList middleName = ((Element) person.item(i)).getElementsByTagName(bcol + "Middle"); + NodeList firstName = ((Element) person.item(i)).getElementsByTagNameNS("*", "First"); + NodeList lastName = ((Element) person.item(i)).getElementsByTagNameNS("*", "Last"); + NodeList middleName = ((Element) person.item(i)).getElementsByTagNameNS("*", "Middle"); PersonName name = new PersonName(); if (firstName.getLength() > 0) { name.setFirstname(firstName.item(0).getTextContent()); @@ -589,99 +223,66 @@ private List getSpecificAuthors(String type, Element authors, String return result; } - private void getAuthors(Element authorsElem, String bcol) { - authors = getSpecificAuthors("Author", authorsElem, bcol); - bookAuthors = getSpecificAuthors("BookAuthor", authorsElem, bcol); - editors = getSpecificAuthors("Editor", authorsElem, bcol); - translators = getSpecificAuthors("Translator", authorsElem, bcol); - producerNames = getSpecificAuthors("ProducerName", authorsElem, bcol); - composers = getSpecificAuthors("Composer", authorsElem, bcol); - conductors = getSpecificAuthors("Conductor", authorsElem, bcol); - performers = getSpecificAuthors("Performer", authorsElem, bcol); - writers = getSpecificAuthors("Writer", authorsElem, bcol); - directors = getSpecificAuthors("Director", authorsElem, bcol); - compilers = getSpecificAuthors("Compiler", authorsElem, bcol); - interviewers = getSpecificAuthors("Interviewer", authorsElem, bcol); - interviewees = getSpecificAuthors("Interviewee", authorsElem, bcol); - inventors = getSpecificAuthors("Inventor", authorsElem, bcol); - counsels = getSpecificAuthors("Counsel", authorsElem, bcol); - } + public Element getDOM(Document document) { + Element rootNode = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "Source"); - private List getAuthors(String authors) { - List result = new LinkedList<>(); + for (Map.Entry entry : fields.entrySet()) { + addField(document, rootNode, entry.getKey(), entry.getValue()); + } - if (authors.contains(" and ")) { - String[] names = authors.split(" and "); - for (String name : names) { - result.add(new PersonName(name)); + // based on bibtex content + if (dateAccessed != null) { + Matcher matcher = DATE_PATTERN.matcher(dateAccessed); + if (matcher.matches() && (matcher.groupCount() >= 3)) { + addField(document, rootNode, "Month" + "Accessed", matcher.group(1)); + addField(document, rootNode, "Day" + "Accessed", matcher.group(2)); + addField(document, rootNode, "Year" + "Accessed", matcher.group(3)); } - } else { - result.add(new PersonName(authors)); } - return result; - } - private String getMSBibSourceType(BibEntry bibtex) { - String bibtexType = bibtex.getType(); + Element allAuthors = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "Author"); + + addAuthor(document, allAuthors, "Author", authors); + addAuthor(document, allAuthors, "BookAuthor", bookAuthors); + addAuthor(document, allAuthors, "Editor", editors); + addAuthor(document, allAuthors, "Translator", translators); + addAuthor(document, allAuthors, "ProducerName", producerNames); + addAuthor(document, allAuthors, "Composer", composers); + addAuthor(document, allAuthors, "Conductor", conductors); + addAuthor(document, allAuthors, "Performer", performers); + addAuthor(document, allAuthors, "Writer", writers); + addAuthor(document, allAuthors, "Director", directors); + addAuthor(document, allAuthors, "Compiler", compilers); + addAuthor(document, allAuthors, "Interviewer", interviewers); + addAuthor(document, allAuthors, "Interviewee", interviewees); + addAuthor(document, allAuthors, "Inventor", inventors); + addAuthor(document, allAuthors, "Counsel", counsels); + + rootNode.appendChild(allAuthors); - String result = "Misc"; - if ("book".equalsIgnoreCase(bibtexType)) { - result = "Book"; - } else if ("inbook".equalsIgnoreCase(bibtexType)) { - result = "BookSection"; - bibTexEntry = "inbook"; - } /* SM 2010.10: generalized */ else if ("booklet".equalsIgnoreCase(bibtexType)) { - result = "BookSection"; - bibTexEntry = "booklet"; - } else if ("incollection".equalsIgnoreCase(bibtexType)) { - result = "BookSection"; - bibTexEntry = "incollection"; - } else if ("article".equalsIgnoreCase(bibtexType)) { - result = "JournalArticle"; - } else if ("inproceedings".equalsIgnoreCase(bibtexType)) { - result = "ConferenceProceedings"; - bibTexEntry = "inproceedings"; - } /* SM 2010.10: generalized */ else if ("conference".equalsIgnoreCase(bibtexType)) { - result = "ConferenceProceedings"; - bibTexEntry = "conference"; - } else if ("proceedings".equalsIgnoreCase(bibtexType)) { - result = "ConferenceProceedings"; - bibTexEntry = "proceedings"; - } else if ("collection".equalsIgnoreCase(bibtexType)) { - result = "ConferenceProceedings"; - bibTexEntry = "collection"; - } else if ("techreport".equalsIgnoreCase(bibtexType)) { - result = "Report"; - bibTexEntry = "techreport"; - } /* SM 2010.10: generalized */ else if ("manual".equalsIgnoreCase(bibtexType)) { - result = "Report"; - bibTexEntry = "manual"; - } else if ("mastersthesis".equalsIgnoreCase(bibtexType)) { - result = "Report"; - bibTexEntry = "mastersthesis"; - } else if ("phdthesis".equalsIgnoreCase(bibtexType)) { - result = "Report"; - bibTexEntry = "phdthesis"; - } else if ("unpublished".equalsIgnoreCase(bibtexType)) { - result = "Report"; - bibTexEntry = "unpublished"; - } else if ("patent".equalsIgnoreCase(bibtexType)) { - result = "Patent"; - } else if ("misc".equalsIgnoreCase(bibtexType)) { - result = "Misc"; - } else if ("electronic".equalsIgnoreCase(bibtexType)) { - result = "Misc"; - bibTexEntry = "electronic"; + if (pages != null) { + addField(document, rootNode, "Pages", pages.toString("-")); } + addField(document, rootNode, "StandardNumber", standardNumber); + addField(document, rootNode, "ConferenceName", conferenceName); - return result; + addAddress(document, rootNode, address); + + addField(document, rootNode, "ThesisType", thesisType); + addField(document, rootNode, "InternetSiteTitle", internetSiteTitle); + + addField(document, rootNode, "PublicationTitle", publicationTitle); + addField(document, rootNode, "AlbumTitle", albumTitle); + addField(document, rootNode, "BroadcastTitle", broadcastTitle); + + return rootNode; } private void addField(Document document, Element parent, String name, String value) { if (value == null) { return; } - Element elem = document.createElement(B_COLON + name); + Element elem = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + name); elem.appendChild(document.createTextNode(StringUtil.stripNonValidXMLCharacters(value))); parent.appendChild(elem); } @@ -690,10 +291,10 @@ private void addAuthor(Document document, Element allAuthors, String entryName, if (authorsLst == null) { return; } - Element authorTop = document.createElement(B_COLON + entryName); - Element nameList = document.createElement(B_COLON + "NameList"); + Element authorTop = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + entryName); + Element nameList = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "NameList"); for (PersonName name : authorsLst) { - Element person = document.createElement(B_COLON + "Person"); + Element person = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "Person"); addField(document, person, "Last", name.getSurname()); addField(document, person, "Middle", name.getMiddlename()); addField(document, person, "First", name.getFirstname()); @@ -715,384 +316,7 @@ private void addAddress(Document document, Element parent, String address) { addField(document, parent, "StateProvince", matcher.group(2)); addField(document, parent, "CountryRegion", matcher.group(3)); } else { - /* SM: 2010.10 generalized */ addField(document, parent, "City", address); } } - - private void addDate(Document document, Element parent, String date, String extra) { - if (date == null) { - return; - } - - Matcher matcher = DATE_PATTERN.matcher(date); - if (matcher.matches() && (matcher.groupCount() >= 3)) { - addField(document, parent, "Month" + extra, matcher.group(1)); - addField(document, parent, "Day" + extra, matcher.group(2)); - addField(document, parent, "Year" + extra, matcher.group(3)); - } - } - - public Element getDOMrepresentation(Document document) { - - Element msbibEntry = document.createElement(B_COLON + "Source"); - - addField(document, msbibEntry, "SourceType", sourceType); - addField(document, msbibEntry, BIBTEX + "Entry", bibTexEntry); - - addField(document, msbibEntry, "Tag", tag); - addField(document, msbibEntry, "GUID", GUID); - if (LCID >= 0) { - addField(document, msbibEntry, "LCID", Integer.toString(LCID)); - } - addField(document, msbibEntry, "Title", title); - addField(document, msbibEntry, "Year", year); - addField(document, msbibEntry, "ShortTitle", shortTitle); - addField(document, msbibEntry, "Comments", comments); - - Element allAuthors = document.createElement(B_COLON + "Author"); - - addAuthor(document, allAuthors, "Author", authors); - String bookAuthor = "BookAuthor"; - addAuthor(document, allAuthors, bookAuthor, bookAuthors); - addAuthor(document, allAuthors, "Editor", editors); - addAuthor(document, allAuthors, "Translator", translators); - addAuthor(document, allAuthors, "ProducerName", producerNames); - addAuthor(document, allAuthors, "Composer", composers); - addAuthor(document, allAuthors, "Conductor", conductors); - addAuthor(document, allAuthors, "Performer", performers); - addAuthor(document, allAuthors, "Writer", writers); - addAuthor(document, allAuthors, "Director", directors); - addAuthor(document, allAuthors, "Compiler", compilers); - addAuthor(document, allAuthors, "Interviewer", interviewers); - addAuthor(document, allAuthors, "Interviewee", interviewees); - addAuthor(document, allAuthors, "Inventor", inventors); - addAuthor(document, allAuthors, "Counsel", counsels); - - msbibEntry.appendChild(allAuthors); - - if (pages != null) { - addField(document, msbibEntry, "Pages", pages.toString("-")); - } - addField(document, msbibEntry, "Volume", volume); - addField(document, msbibEntry, "NumberVolumes", numberOfVolumes); - addField(document, msbibEntry, "Edition", edition); - addField(document, msbibEntry, "StandardNumber", standardNumber); - addField(document, msbibEntry, "Publisher", publisher); - - addAddress(document, msbibEntry, address); - - addField(document, msbibEntry, "BookTitle", bookTitle); - addField(document, msbibEntry, "ChapterNumber", chapterNumber); - - addField(document, msbibEntry, "JournalName", journalName); - addField(document, msbibEntry, "Issue", issue); - addField(document, msbibEntry, "PeriodicalTitle", periodicalTitle); - addField(document, msbibEntry, "ConferenceName", conferenceName); - - addField(document, msbibEntry, "Department", department); - addField(document, msbibEntry, "Institution", institution); - addField(document, msbibEntry, "ThesisType", thesisType); - addField(document, msbibEntry, "InternetSiteTitle", internetSiteTitle); - - addDate(document, msbibEntry, dateAccessed, "Accessed"); - - /* SM 2010.10 added month export */ - addField(document, msbibEntry, "Month", month); - - addField(document, msbibEntry, "DOI", doi); - addField(document, msbibEntry, "URL", url); - addField(document, msbibEntry, "ProductionCompany", productionCompany); - addField(document, msbibEntry, "PublicationTitle", publicationTitle); - addField(document, msbibEntry, "Medium", medium); - addField(document, msbibEntry, "AlbumTitle", albumTitle); - addField(document, msbibEntry, "RecordingNumber", recordingNumber); - addField(document, msbibEntry, "Theater", theater); - addField(document, msbibEntry, "Distributor", distributor); - addField(document, msbibEntry, "BroadcastTitle", broadcastTitle); - addField(document, msbibEntry, "Broadcaster", broadcaster); - addField(document, msbibEntry, "Station", station); - addField(document, msbibEntry, "Type", type); - addField(document, msbibEntry, "PatentNumber", patentNumber); - addField(document, msbibEntry, "Court", court); - addField(document, msbibEntry, "Reporter", reporter); - addField(document, msbibEntry, "CaseNumber", caseNumber); - addField(document, msbibEntry, "AbbreviatedCaseNumber", abbreviatedCaseNumber); - - addField(document, msbibEntry, BIBTEX + "Series", bibTexSeries); - addField(document, msbibEntry, BIBTEX + "Abstract", bibTexAbstract); - addField(document, msbibEntry, BIBTEX + "KeyWords", bibTexKeyWords); - addField(document, msbibEntry, BIBTEX + "CrossRef", bibTexCrossRef); - addField(document, msbibEntry, BIBTEX + "HowPublished", bibTex_HowPublished); - addField(document, msbibEntry, BIBTEX + "Affiliation", bibTexAffiliation); - addField(document, msbibEntry, BIBTEX + "Contents", bibTexContents); - addField(document, msbibEntry, BIBTEX + "Copyright", bibTexCopyright); - addField(document, msbibEntry, BIBTEX + "Price", bibTexPrice); - addField(document, msbibEntry, BIBTEX + "Size", bibTexSize); - - /* SM: 2010.10 end intype, paper support */ - addField(document, msbibEntry, BIBTEX + "InType", bibTexInType); - addField(document, msbibEntry, BIBTEX + "Paper", bibTexPaper); - - return msbibEntry; - } - - private void parseSingleStandardNumber(String type, String bibtype, String standardNum, Map map) { - // tested using http://www.javaregex.com/test.html - Pattern pattern = Pattern.compile(':' + type + ":(.[^:]+)"); - Matcher matcher = pattern.matcher(standardNum); - if (matcher.matches()) { - map.put(bibtype, matcher.group(1)); - } - } - - private void parseStandardNumber(String standardNum, Map map) { - if (standardNumber == null) { - return; - } - parseSingleStandardNumber("ISBN", "isbn", standardNum, map); /* SM: 2010.10: lower case */ - parseSingleStandardNumber("ISSN", "issn", standardNum, map); /* SM: 2010.10: lower case */ - parseSingleStandardNumber("LCCN", "lccn", standardNum, map); /* SM: 2010.10: lower case */ - parseSingleStandardNumber("MRN", "mrnumber", standardNum, map); - /* SM: 2010.10 begin DOI support */ - parseSingleStandardNumber("DOI", "doi", standardNum, map); - /* SM: 2010.10 end DOI support */ - } - - private void addAuthor(Map map, String type, List authors) { - if (authors == null) { - return; - } - String allAuthors = authors.stream().map(PersonName::getFullname).collect(Collectors.joining(" and ")); - - map.put(type, allAuthors); - } - - private EntryType mapMSBibToBibtexType(String msbib) { - EntryType bibtex; - switch (msbib) { - case "Book": - bibtex = BibtexEntryTypes.BOOK; - break; - case "BookSection": - bibtex = BibtexEntryTypes.INBOOK; - break; - case "JournalArticle": - case "ArticleInAPeriodical": - bibtex = BibtexEntryTypes.ARTICLE; - break; - case "ConferenceProceedings": - bibtex = BibtexEntryTypes.CONFERENCE; - break; - case "Report": - bibtex = BibtexEntryTypes.TECHREPORT; - break; - case "InternetSite": - case "DocumentFromInternetSite": - case "ElectronicSource": - case "Art": - case "SoundRecording": - case "Performance": - case "Film": - case "Interview": - case "Patent": - case "Case": - default: - bibtex = BibtexEntryTypes.MISC; - break; - } - - return bibtex; - } - - public BibEntry getBibtexRepresentation() { - - BibEntry entry; - if (tag == null) { - entry = new BibEntry(ImportFormat.DEFAULT_BIBTEXENTRY_ID, mapMSBibToBibtexType(sourceType).getName()); - } else { - entry = new BibEntry(tag, mapMSBibToBibtexType(sourceType).getName()); // id assumes an existing database so don't - } - - // Todo: add check for BibTexEntry types - - Map hm = new HashMap<>(); - - if (tag != null) { - hm.put(BibEntry.KEY_FIELD, tag); - } - - if (LCID >= 0) { - hm.put("language", getLanguage(LCID)); - } - if (title != null) { - hm.put("title", title); - } - if (year != null) { - hm.put("year", year); - } - if (shortTitle != null) { - hm.put(MSBIB + "shorttitle", shortTitle); - } - if (comments != null) { - hm.put("note", comments); - } - - addAuthor(hm, "author", authors); - addAuthor(hm, MSBIB + "bookauthor", bookAuthors); - addAuthor(hm, "editor", editors); - addAuthor(hm, MSBIB + "translator", translators); - addAuthor(hm, MSBIB + "producername", producerNames); - addAuthor(hm, MSBIB + "composer", composers); - addAuthor(hm, MSBIB + "conductor", conductors); - addAuthor(hm, MSBIB + "performer", performers); - addAuthor(hm, MSBIB + "writer", writers); - addAuthor(hm, MSBIB + "director", directors); - addAuthor(hm, MSBIB + "compiler", compilers); - addAuthor(hm, MSBIB + "interviewer", interviewers); - addAuthor(hm, MSBIB + "interviewee", interviewees); - addAuthor(hm, MSBIB + "inventor", inventors); - addAuthor(hm, MSBIB + "counsel", counsels); - - if (pages != null) { - hm.put("pages", pages.toString("--")); - } - if (volume != null) { - hm.put("volume", volume); - } - if (numberOfVolumes != null) { - hm.put(MSBIB + "numberofvolume", numberOfVolumes); - } - if (edition != null) { - hm.put("edition", edition); - } - if (edition != null) { - hm.put("edition", edition); - } - parseStandardNumber(standardNumber, hm); - - if (publisher != null) { - hm.put("publisher", publisher); - } - if (publisher != null) { - hm.put("publisher", publisher); - } - if (address != null) { - hm.put("address", address); - } - if (bookTitle != null) { - hm.put("booktitle", bookTitle); - } - if (chapterNumber != null) { - hm.put("chapter", chapterNumber); - } - if (journalName != null) { - hm.put("journal", journalName); - } - if (issue != null) { - hm.put("number", issue); - } - if (month != null) { - hm.put("month", month); - } - if (periodicalTitle != null) { - hm.put("organization", periodicalTitle); - } - if (conferenceName != null) { - hm.put("organization", conferenceName); - } - if (department != null) { - hm.put("school", department); - } - if (institution != null) { - hm.put("institution", institution); - } - - if (dateAccessed != null) { - hm.put(MSBIB + "accessed", dateAccessed); - } - if (doi != null) { - hm.put("doi", doi); - } - if (url != null) { - hm.put("url", url); - } - if (productionCompany != null) { - hm.put(MSBIB + "productioncompany", productionCompany); - } - - if (medium != null) { - hm.put(MSBIB + "medium", medium); - } - - if (recordingNumber != null) { - hm.put(MSBIB + "recordingnumber", recordingNumber); - } - if (theater != null) { - hm.put(MSBIB + "theater", theater); - } - if (distributor != null) { - hm.put(MSBIB + "distributor", distributor); - } - - if (broadcaster != null) { - hm.put(MSBIB + "broadcaster", broadcaster); - } - if (station != null) { - hm.put(MSBIB + "station", station); - } - if (type != null) { - hm.put(MSBIB + "type", type); - } - if (patentNumber != null) { - hm.put(MSBIB + "patentnumber", patentNumber); - } - if (court != null) { - hm.put(MSBIB + "court", court); - } - if (reporter != null) { - hm.put(MSBIB + "reporter", reporter); - } - if (caseNumber != null) { - hm.put(MSBIB + "casenumber", caseNumber); - } - if (abbreviatedCaseNumber != null) { - hm.put(MSBIB + "abbreviatedcasenumber", abbreviatedCaseNumber); - } - - if (bibTexSeries != null) { - hm.put("series", bibTexSeries); - } - if (bibTexAbstract != null) { - hm.put("abstract", bibTexAbstract); - } - if (bibTexKeyWords != null) { - hm.put("keywords", bibTexKeyWords); - } - if (bibTexCrossRef != null) { - hm.put("crossref", bibTexCrossRef); - } - if (bibTex_HowPublished != null) { - hm.put("howpublished", bibTex_HowPublished); - } - if (bibTexAffiliation != null) { - hm.put("affiliation", bibTexAffiliation); - } - if (bibTexContents != null) { - hm.put("contents", bibTexContents); - } - if (bibTexCopyright != null) { - hm.put("copyright", bibTexCopyright); - } - if (bibTexPrice != null) { - hm.put("price", bibTexPrice); - } - if (bibTexSize != null) { - hm.put("size", bibTexSize); - } - - entry.setField(hm); - return entry; - } - } diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibEntryType.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntryType.java new file mode 100644 index 000000000000..d83f1c331d25 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibEntryType.java @@ -0,0 +1,30 @@ +package net.sf.jabref.logic.msbib; + +/** + * This class represents all supported MSBib entry types. + *

    + * Book, BookSection, JournalArticle, ArticleInAPeriodical, ConferenceProceedings, Report, + * InternetSite, DocumentFromInternetSite, ElectronicSource, Art, SoundRecording, Performance, + * Film, Interview, Patent, Case, Misc + * + * See BIBFORM.XML, shared-bibliography.xsd (ECMA standard) + */ +public enum MSBibEntryType { + ArticleInAPeriodical, + Book, + BookSection, + JournalArticle, + ConferenceProceedings, + Report, + SoundRecording, + Performance, + Art, + DocumentFromInternetSite, + InternetSite, + Film, + Interview, + Patent, + ElectronicSource, + Case, + Misc +} diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java new file mode 100644 index 000000000000..f9561b37e5b6 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java @@ -0,0 +1,130 @@ +package net.sf.jabref.logic.msbib; + +import java.util.Map; +import java.util.TreeMap; + +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.BibtexEntryTypes; + +import com.google.common.collect.HashBiMap; + +public class MSBibMapping { + private static final String BIBTEX_PREFIX = "BIBTEX_"; + private static final String MSBIB_PREFIX = "msbib-"; + + private static final HashBiMap bibtexToMSBib = HashBiMap.create(); + + static { + bibtexToMSBib.put(BibEntry.KEY_FIELD, "Tag"); + bibtexToMSBib.put("title", "Title"); + bibtexToMSBib.put("year", "Year"); + bibtexToMSBib.put("month", "Month"); + bibtexToMSBib.put("note", "Comments"); + bibtexToMSBib.put("volume", "Volume"); + bibtexToMSBib.put("language", "LCID"); + bibtexToMSBib.put("edition", "Edition"); + bibtexToMSBib.put("publisher", "Publisher"); + bibtexToMSBib.put("booktitle", "BookTitle"); + //bibtexToMSBib.put("booktitle", "ConferenceName"); + //bibtexToMSBib.put("pages", "Pages"); + bibtexToMSBib.put("chapter", "ChapterNumber"); + bibtexToMSBib.put("journal", "JournalName"); + bibtexToMSBib.put("number", "Issue"); + bibtexToMSBib.put("school", "Department"); + bibtexToMSBib.put("institution", "Institution"); + bibtexToMSBib.put("doi", "DOI"); + bibtexToMSBib.put("url", "URL"); + // BibTeX only fields + bibtexToMSBib.put("series", BIBTEX_PREFIX + "Series"); + bibtexToMSBib.put("abstract", BIBTEX_PREFIX + "Abstract"); + bibtexToMSBib.put("keywords", BIBTEX_PREFIX + "KeyWords"); + bibtexToMSBib.put("crossref", BIBTEX_PREFIX + "CrossRef"); + bibtexToMSBib.put("howpublished", BIBTEX_PREFIX + "HowPublished"); + bibtexToMSBib.put("affiliation", BIBTEX_PREFIX + "Affiliation"); + bibtexToMSBib.put("contents", BIBTEX_PREFIX + "Contents"); + bibtexToMSBib.put("copyright", BIBTEX_PREFIX + "Copyright"); + bibtexToMSBib.put("price", BIBTEX_PREFIX + "Price"); + bibtexToMSBib.put("size", BIBTEX_PREFIX + "Size"); + bibtexToMSBib.put("intype", BIBTEX_PREFIX + "InType"); + bibtexToMSBib.put("paper", BIBTEX_PREFIX + "Paper"); + // MSBib only fields + bibtexToMSBib.put(MSBIB_PREFIX + "shorttitle", "ShortTitle"); + bibtexToMSBib.put(MSBIB_PREFIX + "numberofvolume", "NumberVolumes"); + bibtexToMSBib.put(MSBIB_PREFIX + "periodical", "PeriodicalTitle"); + //bibtexToMSBib.put(MSBIB_PREFIX + "day", "Day"); + //bibtexToMSBib.put(PREFIX + "accessed", "Accessed"); + bibtexToMSBib.put(MSBIB_PREFIX + "medium", "Medium"); + bibtexToMSBib.put(MSBIB_PREFIX + "recordingnumber", "RecordingNumber"); + bibtexToMSBib.put(MSBIB_PREFIX + "theater", "Theater"); + bibtexToMSBib.put(MSBIB_PREFIX + "distributor", "Distributor"); + bibtexToMSBib.put(MSBIB_PREFIX + "broadcaster", "Broadcaster"); + bibtexToMSBib.put(MSBIB_PREFIX + "station", "Station"); + bibtexToMSBib.put(MSBIB_PREFIX + "type", "Type"); + bibtexToMSBib.put(MSBIB_PREFIX + "patentnumber", "PatentNumber"); + bibtexToMSBib.put(MSBIB_PREFIX + "court", "Court"); + bibtexToMSBib.put(MSBIB_PREFIX + "reporter", "Reporter"); + bibtexToMSBib.put(MSBIB_PREFIX + "casenumber", "CaseNumber"); + bibtexToMSBib.put(MSBIB_PREFIX + "abbreviatedcasenumber", "AbbreviatedCaseNumber"); + bibtexToMSBib.put(MSBIB_PREFIX + "productioncompany", "ProductionCompany"); + } + + public static String getBibTeXEntryType(String msbibType) { + final String defaultType = BibtexEntryTypes.MISC.getName(); + + Map entryTypeMapping = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + entryTypeMapping.put("Book", BibtexEntryTypes.BOOK.getName()); + entryTypeMapping.put("BookSection", BibtexEntryTypes.INBOOK.getName()); + entryTypeMapping.put("JournalArticle", BibtexEntryTypes.ARTICLE.getName()); + entryTypeMapping.put("ArticleInAPeriodical", BibtexEntryTypes.ARTICLE.getName()); + entryTypeMapping.put("ConferenceProceedings", BibtexEntryTypes.CONFERENCE.getName()); + entryTypeMapping.put("Report", BibtexEntryTypes.TECHREPORT.getName()); + + return entryTypeMapping.getOrDefault(msbibType, defaultType); + } + + public static MSBibEntryType getMSBibEntryType(String bibtexType) { + Map entryTypeMapping = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + entryTypeMapping.put("book", MSBibEntryType.Book); + entryTypeMapping.put("inbook", MSBibEntryType.BookSection); + entryTypeMapping.put("booklet", MSBibEntryType.BookSection); + entryTypeMapping.put("incollection", MSBibEntryType.BookSection); + entryTypeMapping.put("article", MSBibEntryType.JournalArticle); + entryTypeMapping.put("inproceedings", MSBibEntryType.ConferenceProceedings); + entryTypeMapping.put("conference", MSBibEntryType.ConferenceProceedings); + entryTypeMapping.put("proceedings", MSBibEntryType.ConferenceProceedings); + entryTypeMapping.put("collection", MSBibEntryType.ConferenceProceedings); + entryTypeMapping.put("techreport", MSBibEntryType.Report); + entryTypeMapping.put("manual", MSBibEntryType.Report); + entryTypeMapping.put("mastersthesis", MSBibEntryType.Report); + entryTypeMapping.put("phdthesis", MSBibEntryType.Report); + entryTypeMapping.put("unpublished", MSBibEntryType.Report); + entryTypeMapping.put("patent", MSBibEntryType.Patent); + entryTypeMapping.put("misc", MSBibEntryType.Misc); + entryTypeMapping.put("electronic", MSBibEntryType.Misc); + + return entryTypeMapping.getOrDefault(bibtexType, MSBibEntryType.Misc); + } + + // http://www.microsoft.com/globaldev/reference/lcid-all.mspx + public static int getLCID(String language) { + // TODO: add language to LCID mapping + // 0 is English + return 0; + } + + // http://www.microsoft.com/globaldev/reference/lcid-all.mspx + public static String getLanguage(int LCID) { + // TODO: add language to LCID mapping + return "english"; + } + + public static String getMSBibField(String bibtexFieldName) { + return bibtexToMSBib.get(bibtexFieldName); + } + + public static String getBibTeXField(String msbibFieldName) { + return bibtexToMSBib.inverse().get(msbibFieldName); + } +} diff --git a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java index 3c140f8bc551..b9c1841fb7f7 100644 --- a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java +++ b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java @@ -8,6 +8,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -54,7 +55,7 @@ public class MSBibExportFormatTestFiles { public static Collection fileNames() throws IOException { try (Stream stream = Files.list(Paths.get(PATH_TO_FILE))) { return stream.map(n -> n.getFileName().toString()).filter(n -> n.endsWith(".bib")) - .filter(n -> n.startsWith("MsBibExportFormat")).collect(Collectors.toList()); + .filter(n -> n.startsWith("MsBib")).collect(Collectors.toList()); } } @@ -80,6 +81,8 @@ public final void testPerformExport() throws IOException, URISyntaxException { List expected = Files.readAllLines(Paths.get(PATH_TO_FILE + xmlFileName)); List exported = Files.readAllLines(Paths.get(tempFilename)); + Collections.sort(expected); + Collections.sort(exported); assertEquals(expected, exported); } } diff --git a/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java b/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java index dbe8178d1cd8..0b0d8b643d24 100644 --- a/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java +++ b/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java @@ -1,13 +1,9 @@ package net.sf.jabref.exporter; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStreamReader; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Paths; import java.util.Collections; import java.util.List; @@ -15,8 +11,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.importer.ParserResult; -import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; @@ -27,7 +21,6 @@ import org.junit.rules.TemporaryFolder; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; public class MsBibExportFormatTest { @@ -57,22 +50,4 @@ public final void testPerformExportWithNoEntry() throws IOException { msBibExportFormat.performExport(databaseContext, tempFileName, charset, entries); assertEquals(Collections.emptyList(), Files.readAllLines(tempFile.toPath())); } - - @Test - public final void testPerformExportWithTestBib() throws IOException { - try (FileInputStream stream = new FileInputStream("src/test/resources/net/sf/jabref/bibtexFiles/test.bib"); - InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { - ParserResult result = BibtexParser.parse(reader); - BibDatabase database = result.getDatabase(); - String tempFilename = tempFile.getCanonicalPath(); - List entries = database.getEntries(); - assertNotNull(entries); - msBibExportFormat.performExport(databaseContext, tempFile.getPath(), charset, entries); - List expected = Files.readAllLines(Paths.get("src/test/resources/net/sf/jabref/exporter/test.xml")); - List exported = Files.readAllLines(Paths.get(tempFilename)); - Collections.sort(expected); - Collections.sort(exported); - assertEquals(expected, exported); - } - } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java index 3e8d1e6d3501..3b9c229fa40a 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java @@ -39,7 +39,7 @@ public void setUp() throws URISyntaxException { @Parameters(name = "{index}: {0}") public static Collection fileNames() { Object[][] data = new Object[][] {{"MsBibImporterTest1"}, {"MsBibImporterTest2"}, {"MsBibImporterTest3"}, - {"MsBibImporterTest4"}, {"MsBibImporterTest5"}, {"MsBibImporterTest6"}}; + {"MsBibImporterTest4"}, {"MsBibImporterTest5"}, {"MsBibImporterTest6"}, {"MsBibLCID"}}; return Arrays.asList(data); } diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java index 0d2ecd85bfab..8a72fc6f8661 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java @@ -36,8 +36,9 @@ public void ignoreWhitespaceInPageNumbers() { } @Test - public void removeWhitespaceForSinglePageNumber() { + public void removeWhitespace() { expectCorrect(" 1 ", "1"); + expectCorrect(" 1 -- 2 ", "1--2"); } @Test diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.bib new file mode 100644 index 000000000000..276562366330 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.bib @@ -0,0 +1,3 @@ +@unpublished{, + title = {Uml{\"a}uts are f\"unny} +} diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.xml b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.xml new file mode 100644 index 000000000000..c96fa94ee040 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.xml @@ -0,0 +1,10 @@ + + + +Report +unpublished +Umläuts are fünny + +unpublished + + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibLCID.bib b/src/test/resources/net/sf/jabref/exporter/MsBibLCID.bib new file mode 100644 index 000000000000..b62dcc57b970 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibLCID.bib @@ -0,0 +1,4 @@ +@Article{, + language = {english} +} + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibLCID.xml b/src/test/resources/net/sf/jabref/exporter/MsBibLCID.xml new file mode 100644 index 000000000000..126619546486 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibLCID.xml @@ -0,0 +1,9 @@ + + + +JournalArticle +0 + +article + + diff --git a/src/test/resources/net/sf/jabref/exporter/test.xml b/src/test/resources/net/sf/jabref/exporter/test.xml deleted file mode 100644 index 3cbf4c63a0fd..000000000000 --- a/src/test/resources/net/sf/jabref/exporter/test.xml +++ /dev/null @@ -1,601 +0,0 @@ - - - -ConferenceProceedings -inproceedings -1358810 -Human-in-the-loop: rethinking security in mobile and pervasive systems -2008 - - - - -Kostakos -Vassilis - - - - -3075-3080 -http://doi.acm.org/10.1145/1358628.1358810 - ISBN: 978-1-60558-012-X DOI: http://doi.acm.org/10.1145/1358628.1358810 -ACM -New York, NY, USA -CHI '08: CHI '08 extended abstracts on Human factors in computing systems -CHI '08: CHI '08 extended abstracts on Human factors in computing systems - - -JournalArticle -820136 -Design and usability in security systems: daily life as a context of use? -2002 - - - - -Clear -Tony - - - - -13-14 -34 -http://doi.acm.org/10.1145/820127.820136 - ISSN: 0097-8418 DOI: http://doi.acm.org/10.1145/820127.820136 -ACM -New York, NY, USA -SIGCSE Bull. -4 - - -JournalArticle -1373163 -Useful Computer Security -2008 - - - - -Churchill -Elizabeth - - -Nelson -Les - - -Smetters -K. -Diana - - - - -10-12 -12 -http://dx.doi.org/10.1109/MIC.2008.67 - ISSN: 1089-7801 DOI: http://dx.doi.org/10.1109/MIC.2008.67 -IEEE Educational Activities Department -Piscataway -NJ -USA -IEEE Internet Computing -3 - - -ConferenceProceedings -inproceedings -00000000 -Are Usability and Security Two Opposite Directions in Computer Systems? -2004 - - - - -Rozinov -Konstantin - - - - - - -JournalArticle -1025014 -Password Memorability and Security: Empirical Results -2004 - - - - -Yan -Jeff - - -Blackwell -Alan - - -Anderson -Ross - - -Grant -Alasdair - - - - -25-31 -2 -http://dx.doi.org/10.1109/MSP.2004.81 - ISSN: 1540-7993 DOI: http://dx.doi.org/10.1109/MSP.2004.81 -IEEE Educational Activities Department -Piscataway -NJ -USA -IEEE Security and Privacy -5 - - -JournalArticle -1102917 -The trouble with login: on usability and computer security in ubiquitous computing -2005 - - - - -Bardram -E. - - - - -357-367 -9 -http://dx.doi.org/10.1007/s00779-005-0347-6 - ISSN: 1617-4909 DOI: http://dx.doi.org/10.1007/s00779-005-0347-6 -Springer-Verlag -London -U -K -Personal Ubiquitous Comput. -6 - - -ConferenceProceedings -inproceedings -1137631 -Extending XP practices to support security requirements engineering -2006 - - - - -Bostr\"{o}m -Gustav - - -W\"{a}yrynen -Jaana - - -Bod\'{e}n -Marine - - -Beznosov -Konstantin - - -Kruchten -Philippe - - - - -11-18 -http://doi.acm.org/10.1145/1137627.1137631 - ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137631 -ACM -New York, NY, USA -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems - - -ConferenceProceedings -inproceedings -1233448 -Increasing security and usability of computer systems with graphical passwords -2007 - - - - -Hinds -Cheryl - - -Ekwueme -Chinedu - - - - -529-530 -http://doi.acm.org/10.1145/1233341.1233448 - ISBN: 978-1-59593-629-5 DOI: http://doi.acm.org/10.1145/1233341.1233448 -ACM -New York, NY, USA -ACM-SE 45: Proceedings of the 45th annual southeast regional conference -ACM-SE 45: Proceedings of the 45th annual southeast regional conference - - -JournalArticle -10250999 -Article with complex Authornames -2004 - - - - -von Hippel -Eric - - -Reagle -Joseph M. -Jr., - - -Sherry -F., Jr. -John - - -van den Huevel -Johan A. -Jr., - - - - -25-31 -2 -http://dx.doi.org/10.1109/MSP.2004.81 - ISSN: 1540-7993 DOI: http://dx.doi.org/10.1109/MSP.2004.81 -IEEE Educational Activities Department -Piscataway -NJ -USA -IEEE Security and Privacy -5 - - -ConferenceProceedings -inproceedings -1132768 -Security and usability: the case of the user authentication methods -2006 - - - - -Braz -Christina - - -Robert -Jean-Marc - - - - -199-203 -http://doi.acm.org/10.1145/1132736.1132768 - ISBN: 1-59593-350-6 DOI: http://doi.acm.org/10.1145/1132736.1132768 -ACM -New York, NY, USA -IHM '06: Proceedings of the 18th International Conferenceof the Association Francophone d'Interaction Homme-Machine -IHM '06: Proceedings of the 18th International Conferenceof the Association Francophone d'Interaction Homme-Machine - - -ConferenceProceedings -inproceedings -1251435 -Why Johnny can't encrypt: a usability evaluation of PGP 5.0 -1999 - - - - -Whitten -Alma - - -Tygar -D. -J. - - - - -14-14 -USENIX Association -Berkeley -CA -USA -SSYM'99: Proceedings of the 8th conference on USENIX Security Symposium -SSYM'99: Proceedings of the 8th conference on USENIX Security Symposium - - -ConferenceProceedings -inproceedings -1182529 -Question-based authentication using context data -2006 - - - - -Nosseir -Ann - - -Connor -Richard - - -Revie -Crawford - - -Terzis -Sotirios - - - - -429-432 -http://doi.acm.org/10.1145/1182475.1182529 - ISBN: 1-59593-325-5 DOI: http://doi.acm.org/10.1145/1182475.1182529 -ACM -New York, NY, USA -NordiCHI '06: Proceedings of the 4th Nordic conference on Human-computer interaction -NordiCHI '06: Proceedings of the 4th Nordic conference on Human-computer interaction - - -ConferenceProceedings -inproceedings -1137636 -Trust and tamper-proof software delivery -2006 - - - - -Naedele -Martin - - -Koch -E. -Thomas - - - - -51-58 -http://doi.acm.org/10.1145/1137627.1137636 - ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137636 -ACM -New York, NY, USA -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems - - -ConferenceProceedings -inproceedings -1314293 -Randomized radon transforms for biometric authentication via fingerprint hashing -2007 - - - - -Jakubowski -H. -Mariusz - - -Venkatesan -Ramarathnam - - - - -90-94 -http://doi.acm.org/10.1145/1314276.1314293 - ISBN: 978-1-59593-884-8 DOI: http://doi.acm.org/10.1145/1314276.1314293 -ACM -New York, NY, USA -DRM '07: Proceedings of the 2007 ACM workshop on Digital Rights Management -DRM '07: Proceedings of the 2007 ACM workshop on Digital Rights Management - - -ConferenceProceedings -inproceedings -1137628 -Introduction to software engineering for secure systems: SESS06 -- secure by design -2006 - - - - -Bruschi -Danilo - - -Win -De -Bart - - -Monga -Mattia - - - - -1-2 -http://doi.acm.org/10.1145/1137627.1137628 - ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137628 -ACM -New York, NY, USA -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems - - -ConferenceProceedings -inproceedings -1073004 -Two experiences designing for effective security -2005 - - - - -de Paula -Rog\'{e}rio - - -Ding -Xianghua - - -Dourish -Paul - - -Nies -Kari - - -Pillet -Ben - - -Redmiles -David - - -Ren -Jie - - -Rode -Jennifer - - -Filho -Silva -Roberto - - - - -25-34 -http://doi.acm.org/10.1145/1073001.1073004 - ISBN: 1-59593-178-3 DOI: http://doi.acm.org/10.1145/1073001.1073004 -ACM -New York, NY, USA -SOUPS '05: Proceedings of the 2005 symposium on Usable privacy and security -SOUPS '05: Proceedings of the 2005 symposium on Usable privacy and security - - -ConferenceProceedings -inproceedings -1137633 -How secure is AOP and what can we do about it? -2006 - - - - -Win -De -Bart - - -Piessens -Frank - - -Joosen -Wouter - - - - -27-34 -http://doi.acm.org/10.1145/1137627.1137633 - ISBN: 1-59593-411-1 DOI: http://doi.acm.org/10.1145/1137627.1137633 -ACM -New York, NY, USA -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems -SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems - - -Book -1098730 -Security and Usability -2005 - - - - -Cranor -Lorrie - - -Garfinkel -Simson - - - - - ISBN: 0596008279 -O'Reilly Media, Inc. - - -ConferenceProceedings -inproceedings -1143122 -Aligning usability and security: a usability study of Polaris -2006 - - - - -DeWitt -J. -Alexander - - -Kuljis -Jasna - - - - -1-7 -http://doi.acm.org/10.1145/1143120.1143122 - ISBN: 1-59593-448-0 DOI: http://doi.acm.org/10.1145/1143120.1143122 -ACM -New York, NY, USA -SOUPS '06: Proceedings of the second symposium on Usable privacy and security -SOUPS '06: Proceedings of the second symposium on Usable privacy and security - - diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest1.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest1.xml index 649ba1729587..0b5670840fec 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest1.xml +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest1.xml @@ -5,7 +5,6 @@ raey 0 Agile Entwicklung Web-basierter Systeme -BookSection 2002 237-248 44 diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib index 282796f3be70..1907e883d4bb 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib @@ -11,6 +11,7 @@ @Article{ copyright = {cop}, crossref = {cross}, edition = {10}, + language = {english}, howpublished = {how}, institution = {Institution}, msbib-abbreviatedcasenumber = {abb}, @@ -29,6 +30,7 @@ @Article{ msbib-station = {stat}, msbib-theater = {th}, msbib-type = {type}, + msbib-periodical = {Besondere Turingmaschinen}, organization = {Besondere Turingmaschinen}, price = {10}, school = {Gymnasium Unterrieden}, diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.xml index 1d57a98ff779..8a475457cfd2 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.xml +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.xml @@ -21,13 +21,13 @@ Stuttgart Bawü Deutschland -z +0 July 3 2010 Turingmaschinen 3 -Besondere TuringMaschinen +Besondere Turingmaschinen Besondere Turingmaschinen Gymnasium Unterrieden Institution diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest3.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest3.xml index bc251f1d8b24..a927f422effa 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest3.xml +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest3.xml @@ -16,7 +16,6 @@ 0 Agile Entwicklung Web-basierter Systeme -BookSection 2002 237-248 44 @@ -26,5 +25,5 @@ 3 http://dx.doi.org/10.1007/BF03250842 software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development - + diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest4.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest4.xml index e466ea7198ff..3473e80bd888 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest4.xml +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest4.xml @@ -5,7 +5,6 @@ raey 0 Agile Entwicklung Web-basierter Systeme -BookSection 2002 237-248 44 @@ -15,5 +14,5 @@ 3 http://dx.doi.org/10.1007/BF03250842 software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development - + diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest5.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest5.xml index 7688a2b051e3..87eb55d1792c 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest5.xml +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest5.xml @@ -5,7 +5,6 @@ 0 Agile Entwicklung Web-basierter Systeme -BookSection 2002 237-248 44 @@ -15,5 +14,5 @@ 3 http://dx.doi.org/10.1007/BF03250842 software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development - + diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest6.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest6.xml index 45fa51229b75..13f34bd052cc 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest6.xml +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest6.xml @@ -5,7 +5,6 @@ 0 Agile Entwicklung Web-basierter Systeme -BookSection 2002 237-248 44 @@ -15,5 +14,5 @@ 3 http://dx.doi.org/10.1007/BF03250842 software development processes; agile software development environments; time-to-market; Extreme Programming; Crystal methods family; Adaptive Software Development - + diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.bib new file mode 100644 index 000000000000..b62dcc57b970 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.bib @@ -0,0 +1,4 @@ +@Article{, + language = {english} +} + diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.xml new file mode 100644 index 000000000000..7eb75b141724 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibLCID.xml @@ -0,0 +1,7 @@ + + + +JournalArticle +0 + + From fea313fdfcf74d47639f331d28e84ea0aa19dac5 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 5 Jun 2016 19:50:46 +0200 Subject: [PATCH 131/268] Correct link to label patterns help (#1473) --- src/main/java/net/sf/jabref/gui/help/HelpFiles.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/gui/help/HelpFiles.java b/src/main/java/net/sf/jabref/gui/help/HelpFiles.java index 58070eb9e0cf..9af4d53ce9bc 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpFiles.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpFiles.java @@ -41,7 +41,7 @@ public enum HelpFiles { SPECIAL_FIELDS( "specialFieldsHelp"), LABEL_PATTERN( - "labelPatternHelp"), + "LabelPatterns"), OWNER( "OwnerHelp"), TIMESTAMP( From 7469ffda37e1f3833f89f675620eecdd32e980b2 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 5 Jun 2016 20:17:57 +0200 Subject: [PATCH 132/268] Fix help file links and add test to ensure each link at least exists for english translation. --- .../net/sf/jabref/gui/help/HelpFiles.java | 153 ++++++------------ .../net/sf/jabref/gui/help/HelpFilesTest.java | 21 +++ 2 files changed, 68 insertions(+), 106 deletions(-) create mode 100644 src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java diff --git a/src/main/java/net/sf/jabref/gui/help/HelpFiles.java b/src/main/java/net/sf/jabref/gui/help/HelpFiles.java index 9af4d53ce9bc..cda5ea2686f5 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpFiles.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpFiles.java @@ -16,129 +16,70 @@ package net.sf.jabref.gui.help; /** - * This enum globally defines all help pages with the name of the markdown file in the help repository at github - * @see help.jabref.org@github - * + * This enum globally defines all help pages with the name of the markdown file in the help repository at Github. * + * @see help.jabref.org@github */ public enum HelpFiles { - COMMAND_LINE( - ""), - + COMMAND_LINE(""), //Empty because it refers to the TOC/index - CONTENTS( - ""), - ENTRY_EDITOR( - "EntryEditorHelp"), - STRING_EDITOR( - "StringEditorHelp"), - SEARCH( - "SearchHelp"), - GROUP( - "GroupsHelp"), - CONTENT_SELECTOR( - "ContentSelectorHelp"), - SPECIAL_FIELDS( - "specialFieldsHelp"), - LABEL_PATTERN( - "LabelPatterns"), - OWNER( - "OwnerHelp"), - TIMESTAMP( - "TimeStampHelp"), - CUSTOM_EXPORTS( - "CustomExports"), - CUSTOM_EXPORTS_NAME_FORMATTER( - "CustomExports#NameFormatter"), - CUSTOM_IMPORTS( - "CustomImports"), - GENERAL_FIELDS( - "GeneralFields"), - IMPORT_INSPECTION( - "ImportInspectionDialog"), - REMOTE( - "RemoteHelp"), - JOURNAL_ABBREV( - "JournalAbbreviations"), - REGEX_SEARCH( - "ExternalFiles#RegularExpressionSearch"), - PREVIEW( - "PreviewHelp"), - AUTOSAVE( - "Autosave"), - + CONTENTS(""), + ENTRY_EDITOR("EntryEditorHelp"), + STRING_EDITOR("StringEditorHelp"), + SEARCH("SearchHelp"), + GROUP("GroupsHelp"), + CONTENT_SELECTOR("ContentSelectorHelp"), + SPECIAL_FIELDS("SpecialFieldsHelp"), + LABEL_PATTERN("LabelPatterns"), + OWNER("OwnerHelp"), + TIMESTAMP("TimeStampHelp"), + CUSTOM_EXPORTS("CustomExports"), + CUSTOM_EXPORTS_NAME_FORMATTER("CustomExports#NameFormatter"), + CUSTOM_IMPORTS("CustomImports"), + GENERAL_FIELDS("GeneralFields"), + IMPORT_INSPECTION("ImportInspectionDialog"), + REMOTE("RemoteHelp"), + JOURNAL_ABBREV("JournalAbbreviations"), + REGEX_SEARCH("ExternalFiles#RegularExpressionSearch"), + PREVIEW("PreviewHelp"), + AUTOSAVE("Autosave"), //The help page covers both OO and LO. - OPENOFFICE_LIBREOFFICE( - "OpenOfficeIntegration"), - - FETCHER_ACM( - "ACMPortalHelp"), - - FETCHER_ADS( - "ADSHelp"), - - FETCHER_CITESEERX( - "CiteSeerHelp"), - - FETCHER_DBLP( - "DBLPHelp"), - - FETCHER_DIVA_TO_BIBTEX( - "DiVAtoBibTeXHelp"), - - FETCHER_DOAJ( - "DOAJHelp"), - - FETCHER_DOI_TO_BIBTEX( - "DOItoBibTeXHelp"), - - FETCHER_GOOGLE_SCHOLAR( - "GoogleScholarHelp"), - - FETCHER_GVK( - "GVKHelp"), + OPENOFFICE_LIBREOFFICE("OpenOfficeIntegration"), + FETCHER_ACM("ACMPortalHelp"), + FETCHER_ADS("ADSHelp"), + FETCHER_CITESEERX("CiteSeerHelp"), + FETCHER_DBLP("DBLPHelp"), + FETCHER_DIVA_TO_BIBTEX("DiVAtoBibTeXHelp"), + FETCHER_DOAJ("DOAJHelp"), + FETCHER_DOI_TO_BIBTEX("DOItoBibTeXHelp"), + FETCHER_GOOGLE_SCHOLAR("GoogleScholarHelp"), + FETCHER_GVK("GVKHelp"), + FETCHER_IEEEXPLORE("IEEEXploreHelp"), + FETCHER_INSPIRE("INSPIRE"), + FETCHER_ISBN_TO_BIBTEX("ISBNtoBibTeXHelp"), + FETCHER_MEDLINE("MedlineHelp"), + FETCHER_OAI2_ARXIV("arXivHelp"), + FETCHER_SPRINGER("SpringerHelp"), + FETCHER_SCIENCEDIRECT(""), + FETCHER_BIBSONOMY_SCRAPER(""); - FETCHER_IEEEXPLORE( - "IEEEXploreHelp"), - - FETCHER_INSPIRE( - "INSPIRE"), - - FETCHER_ISBN_TO_BIBTEX( - "ISBNtoBibTeXHelp"), - FETCHER_MEDLINE( - "MedlineHelp"), - - FETCHER_OAI2_ARXIV( - "arXivHelp"), - - FETCHER_SPRINGER( - "SpringerHelp"), - - FETCHER_SCIENCEDIRECT( - ""), - - FETCHER_BIBSONOMY_SCRAPER( - ""); + private final String pageName; /** + * Sets the URL path part of the help page. * - * @param pageName The filename of the help page + * @param pageName the URL path part of the help page */ HelpFiles(String pageName) { this.pageName = pageName; } - - private final String pageName; - - /** - * Get the filename of a help page - * @return The filename of the associated help page + * Returns the URL path part of the help page. + * + * @return the URL path part of the help page */ public String getPageName() { return pageName; } - } diff --git a/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java b/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java new file mode 100644 index 000000000000..a2cc66f65d95 --- /dev/null +++ b/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java @@ -0,0 +1,21 @@ +package net.sf.jabref.gui.help; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class HelpFilesTest { + private final String jabrefHelp = "http://help.jabref.org/en/"; + @Test + public void referToValidPage() throws IOException { + for (HelpFiles help : HelpFiles.values()) { + URL url = new URL(jabrefHelp + help.getPageName()); + HttpURLConnection http = (HttpURLConnection) url.openConnection(); + assertEquals(200, http.getResponseCode()); + } + } +} \ No newline at end of file From 466140ca927488c25fbf148050f8460c4e972395 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 5 Jun 2016 20:18:55 +0200 Subject: [PATCH 133/268] Newline --- src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java b/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java index a2cc66f65d95..04e3c188bd7c 100644 --- a/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java +++ b/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java @@ -18,4 +18,4 @@ public void referToValidPage() throws IOException { assertEquals(200, http.getResponseCode()); } } -} \ No newline at end of file +} From 39dc8d95991c8f23deade63e757aa7b4eab4018d Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 5 Jun 2016 20:23:00 +0200 Subject: [PATCH 134/268] Fix #1434: Static groups are now longer displayed as dynamic ones --- CHANGELOG.md | 2 +- src/main/java/net/sf/jabref/gui/groups/GroupDialog.java | 6 +++--- src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java | 5 +++++ src/main/java/net/sf/jabref/util/Util.java | 6 +++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c649f8abffb..72a9b3194a1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Fixed - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - +- Fixed [#1434](https://github.com/JabRef/jabref/issues/1434): Static groups are now longer displayed as dynamic ones ### Removed diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index 815b5a9d3e5f..d0e6989c75f1 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -347,7 +347,7 @@ public void actionPerformed(ActionEvent e) { m_sgCaseSensitive.addItemListener(itemListener); // configure for current type - if (editedGroup instanceof KeywordGroup) { + if (editedGroup.getClass() == KeywordGroup.class) { KeywordGroup group = (KeywordGroup) editedGroup; m_name.setText(group.getName()); m_kgSearchField.setText(group.getSearchField()); @@ -356,7 +356,7 @@ public void actionPerformed(ActionEvent e) { m_kgRegExp.setSelected(group.isRegExp()); m_keywordsRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); - } else if (editedGroup instanceof SearchGroup) { + } else if (editedGroup.getClass() == SearchGroup.class) { SearchGroup group = (SearchGroup) editedGroup; m_name.setText(group.getName()); m_sgSearchExpression.setText(group.getSearchExpression()); @@ -364,7 +364,7 @@ public void actionPerformed(ActionEvent e) { m_sgRegExp.setSelected(group.isRegExp()); m_searchRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); - } else if (editedGroup instanceof ExplicitGroup) { + } else if (editedGroup.getClass() == ExplicitGroup.class) { m_name.setText(editedGroup.getName()); m_explicitRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); diff --git a/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java b/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java index 83802db7eec7..fc3a801b0764 100644 --- a/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java @@ -172,4 +172,9 @@ public String getTypeId() { public int hashCode() { return super.hashCode(); } + + @Override + public boolean isDynamic() { + return false; + } } diff --git a/src/main/java/net/sf/jabref/util/Util.java b/src/main/java/net/sf/jabref/util/Util.java index 6e2478be077c..c2562cdd64ac 100644 --- a/src/main/java/net/sf/jabref/util/Util.java +++ b/src/main/java/net/sf/jabref/util/Util.java @@ -74,8 +74,8 @@ public static boolean warnAssignmentSideEffects(AbstractGroup group, Component p /** * Warns the user of undesired side effects of an explicit assignment/removal of entries to/from this group. * Currently there are four types of groups: AllEntriesGroup, SearchGroup - do not support explicit assignment. - * ExplicitGroup - never modifies entries. KeywordGroup - only this modifies entries upon assignment/removal. - * Modifications are acceptable unless they affect a standard field (such as "author") besides the "keywords" field. + * ExplicitGroup and KeywordGroup - this modifies entries upon assignment/removal. + * Modifications are acceptable unless they affect a standard field (such as "author") besides the "keywords" or "groups' field. * * @param parent The Component used as a parent when displaying a confirmation dialog. * @return true if the assignment has no undesired side effects, or the user chose to perform it anyway. false @@ -87,7 +87,7 @@ public static boolean warnAssignmentSideEffects(List groups, Comp if (group instanceof KeywordGroup) { KeywordGroup kg = (KeywordGroup) group; String field = kg.getSearchField().toLowerCase(); - if ("keywords".equals(field)) { + if ("keywords".equals(field) || "groups".equals(field)) { continue; // this is not undesired } int len = InternalBibtexFields.numberOfPublicFields(); From 6c39395830709109bc0cc72fc6ca12528c81937b Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 5 Jun 2016 20:26:48 +0200 Subject: [PATCH 135/268] Import --- src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java b/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java index 04e3c188bd7c..0dc0d2983953 100644 --- a/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java +++ b/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java @@ -6,7 +6,7 @@ import org.junit.Test; -import static org.junit.Assert.*; +import static junit.framework.TestCase.assertEquals; public class HelpFilesTest { private final String jabrefHelp = "http://help.jabref.org/en/"; From a204089ff3e23123f991de66e7bf21b0c58417fc Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 5 Jun 2016 20:34:35 +0200 Subject: [PATCH 136/268] Update dependencies --- build.gradle | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 27858aa0947f..121a417d5a03 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,3 @@ - import org.gradle.internal.os.OperatingSystem buildscript { @@ -74,7 +73,7 @@ dependencies { compile 'org.apache.pdfbox:fontbox:1.8.12' compile 'org.apache.pdfbox:jempbox:1.8.12' - // required for reading write-procted PDFs - see https://github.com/JabRef/jabref/pull/942#issuecomment-209252635 + // required for reading write-protected PDFs - see https://github.com/JabRef/jabref/pull/942#issuecomment-209252635 compile 'org.bouncycastle:bcprov-jdk15on:1.54' compile 'commons-cli:commons-cli:1.3.1' @@ -92,7 +91,7 @@ dependencies { antlr4 'org.antlr:antlr4:4.5.3' compile 'org.antlr:antlr4-runtime:4.5.3' - compile 'mysql:mysql-connector-java:5.1.38' + compile 'mysql:mysql-connector-java:6.0.2' compile 'org.postgresql:postgresql:9.4.1208' compile 'net.java.dev.glazedlists:glazedlists_java15:1.9.1' @@ -102,13 +101,13 @@ dependencies { compile 'commons-logging:commons-logging:1.2' - compile 'org.jsoup:jsoup:1.9.1' + compile 'org.jsoup:jsoup:1.9.2' compile 'com.mashape.unirest:unirest-java:1.4.9' compile 'info.debatty:java-string-similarity:0.13' - compile 'org.apache.logging.log4j:log4j-jcl:2.5' - compile 'org.apache.logging.log4j:log4j-api:2.5' - compile 'org.apache.logging.log4j:log4j-core:2.5' + compile 'org.apache.logging.log4j:log4j-jcl:2.6' + compile 'org.apache.logging.log4j:log4j-api:2.6' + compile 'org.apache.logging.log4j:log4j-core:2.6' testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' From 6847a867eafce249d40b4ef6ff255fb232bd26a8 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 5 Jun 2016 20:41:24 +0200 Subject: [PATCH 137/268] Revert mysql update --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 121a417d5a03..ca35e388a5c0 100644 --- a/build.gradle +++ b/build.gradle @@ -91,7 +91,7 @@ dependencies { antlr4 'org.antlr:antlr4:4.5.3' compile 'org.antlr:antlr4-runtime:4.5.3' - compile 'mysql:mysql-connector-java:6.0.2' + compile 'mysql:mysql-connector-java:5.1.38' compile 'org.postgresql:postgresql:9.4.1208' compile 'net.java.dev.glazedlists:glazedlists_java15:1.9.1' From 8d5c8b260f739b332152eb55163fe52927a6e466 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sun, 5 Jun 2016 21:05:50 +0200 Subject: [PATCH 138/268] Remove codacy as its just meaningless right now --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 81856cd0ae8a..2ca43e8e5e43 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ [![Donation](https://img.shields.io/badge/donate-paypal-orange.svg)](https://www.paypal.com/cgi-bin/webscr?item_name=JabRef+Bibliography+Manager&cmd=_donations&lc=US¤cy_code=EUR&business=jabrefmail%40gmail.com) [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/pr)](http://www.issuestats.com/github/jabref/jabref) [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/issue)](http://www.issuestats.com/github/jabref/jabref) -[![Codacy Badge](https://api.codacy.com/project/badge/grade/327430c894e04086a5bfef618fa44f36)](https://www.codacy.com/app/simonharrer/jabref) This version is a development version. Features may not work as expected. From 241b336de46a943feb90579a28b512b24eb4cd01 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Mon, 6 Jun 2016 15:42:46 +0200 Subject: [PATCH 139/268] Fix #1476 NPE when importing from SQL DB because of missing DatabaseMode (#1477) --- CHANGELOG.md | 2 +- src/main/java/net/sf/jabref/JabRefPreferences.java | 14 ++++++++++++++ .../jabref/gui/labelpattern/LabelPatternPanel.java | 10 ++++------ .../net/sf/jabref/sql/importer/DbImportAction.java | 10 ++++------ 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c649f8abffb..b73aebea0e16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Fixed - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - +- Fixed [#1476](https://github.com/JabRef/jabref/issues/1476): NPE when importing from SQL DB because of missing DatabaseMode ### Removed diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index bbdc6e774213..dce46b1efa3e 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -71,6 +71,7 @@ import net.sf.jabref.logic.remote.RemotePreferences; import net.sf.jabref.logic.util.OS; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryUtil; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -1037,6 +1038,19 @@ public Color getDefaultColor(String key) { return new Color(rgb[0], rgb[1], rgb[2]); } + /** + * Returns the default BibDatabase mode, which can be either BIBTEX or BIBLATEX. + * + * @return the default BibDatabaseMode + */ + public BibDatabaseMode getDefaultBibDatabaseMode() { + if (getBoolean(BIBLATEX_DEFAULT_MODE)) { + return BibDatabaseMode.BIBLATEX; + } else { + return BibDatabaseMode.BIBTEX; + } + } + /** * Set the default value for a key. This is useful for plugins that need to add default values for the prefs keys * they use. diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java index 154463176751..9d97458fe43c 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java @@ -120,13 +120,11 @@ private void buildGUI() { // check mode of currently used DB if (panel != null) { mode = panel.getBibDatabaseContext().getMode(); - } else { // use preferences value if no DB is open - if (Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE)) { - mode = BibDatabaseMode.BIBLATEX; - } else { - mode = BibDatabaseMode.BIBTEX; - } + } else { + // use preferences value if no DB is open + mode = Globals.prefs.getDefaultBibDatabaseMode(); } + for (EntryType type : EntryTypes.getAllValues(mode)) { textFields.put(type.getName().toLowerCase(), addEntryType(pan, type, y)); y++; diff --git a/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java b/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java index 230c07961082..9b2ea62b9757 100644 --- a/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java +++ b/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java @@ -27,6 +27,7 @@ import javax.swing.JOptionPane; import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.MnemonicAwareAction; @@ -69,11 +70,8 @@ public AbstractAction getAction() { } class DbImpAction extends MnemonicAwareAction { - public DbImpAction() { - super(); putValue(Action.NAME, Localization.menuTitle("Import from external SQL database")); - } @Override @@ -151,14 +149,14 @@ private void performImport() { Localization.lang("There are no available databases to be imported"), Localization.lang("Import from SQL database"), JOptionPane.INFORMATION_MESSAGE); } else { - DBImportExportDialog dialogo = new DBImportExportDialog(frame, matrix, - DBImportExportDialog.DialogType.IMPORTER); + DBImportExportDialog dialogo = new DBImportExportDialog(frame, matrix, DBImportExportDialog.DialogType.IMPORTER); if (dialogo.removeAction) { String dbName = dialogo.selectedDB; DatabaseUtil.removeDB(dialogo, dbName, conn, databaseContext); performImport(); } else if (dialogo.moreThanOne) { - databases = importer.performImport(dbs, dialogo.listOfDBs, frame.getCurrentBasePanel().getBibDatabaseContext().getMode()); + // use default DB mode for import + databases = importer.performImport(dbs, dialogo.listOfDBs, Globals.prefs.getDefaultBibDatabaseMode()); for (DBImporterResult res : databases) { databaseContext = res.getDatabaseContext(); dbs.isConfigValid(true); From 16097e40e3f946a1c5de7a4e5cdcfe89c60c60dc Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 6 Jun 2016 20:36:13 +0200 Subject: [PATCH 140/268] Fixes #1482: Correct number of matched entries is displayed for refining subgroups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue was that, for the number of hits, JabRef only checks if the group taken separately matches the entry. That is, it is completely ignored that the group sits in a tree and might be set up to refine the search of the parent. Taking the example given in #1482, 577 entries satisfy the condition `articlé original` but only 38 are also matched by `articlé`. --- CHANGELOG.md | 1 + .../gui/groups/GroupTreeNodeViewModel.java | 2 +- .../sf/jabref/logic/groups/AbstractGroup.java | 15 ----- .../sf/jabref/logic/groups/GroupTreeNode.java | 16 ++++++ .../logic/groups/AbstractGroupTest.java | 26 --------- .../logic/groups/GroupTreeNodeTest.java | 56 +++++++++++++++++++ 6 files changed, 74 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b73aebea0e16..4e1cfd0fdbfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - Fixed [#1476](https://github.com/JabRef/jabref/issues/1476): NPE when importing from SQL DB because of missing DatabaseMode +- Fixed [#1482](https://github.com/JabRef/jabref/issues/1482): Correct number of matched entries is displayed for refining subgroups ### Removed diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java index 3d9c1fdb5369..417fb12fdfd2 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -197,7 +197,7 @@ public String getText() { && JabRefGUI.getMainFrame() != null) { BasePanel currentBasePanel = JabRefGUI.getMainFrame().getCurrentBasePanel(); if (currentBasePanel != null) { - sb.append(" [").append(group.numberOfHits(currentBasePanel.getDatabase().getEntries())).append(']'); + sb.append(" [").append(node.numberOfHits(currentBasePanel.getDatabase().getEntries())).append(']'); } } diff --git a/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java b/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java index 26026deda4d8..10f1ea3c35d3 100644 --- a/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java @@ -168,21 +168,6 @@ public boolean containsAll(List entries) { return true; } - /** - * Determines the number of entries in the specified list which are matched by this group. - * @param entries list of entries to be searched - * @return number of hits - */ - public int numberOfHits(List entries) { - int hits = 0; - for (BibEntry entry : entries) { - if (this.contains(entry)) { - hits++; - } - } - return hits; - } - /** * Returns true if this group is dynamic, i.e. uses a search definition or * equiv. that might match new entries, or false if this group contains a diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java index 3cae6ac49101..28dd7b2d367c 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java @@ -213,4 +213,20 @@ public String toString() { public GroupTreeNode copyNode() { return new GroupTreeNode(group); } + + /** + * Determines the number of entries in the specified list which are matched by this group. + * @param entries list of entries to be searched + * @return number of hits + */ + public int numberOfHits(List entries) { + int hits = 0; + SearchMatcher matcher = getSearchRule(); + for (BibEntry entry : entries) { + if (matcher.isMatch(entry)) { + hits++; + } + } + return hits; + } } diff --git a/src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java index 8fd8329c6b8f..7a027bfd4497 100644 --- a/src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/AbstractGroupTest.java @@ -18,19 +18,14 @@ package net.sf.jabref.logic.groups; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import net.sf.jabref.model.entry.BibEntry; import org.junit.Before; -import org.junit.Test; import org.mockito.Mockito; -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class AbstractGroupTest { @@ -44,25 +39,4 @@ public void setUp() throws Exception { entries.add(new BibEntry().withField("author", "author1 and author2")); entries.add(new BibEntry().withField("author", "author1")); } - - @Test - public void numberOfHitsReturnsZeroForEmptyList() throws Exception { - assertEquals(0, group.numberOfHits(Collections.emptyList())); - } - - @Test - public void numberOfHitsCallsContainsToDetermineSingleHit() throws Exception { - when(group.contains(any())).then(invocation -> - invocation.getArgumentAt(0, BibEntry.class).getField("author").contains("author2")); - assertEquals(1, group.numberOfHits(entries)); - } - - @Test - public void numberOfHitsCallsContainsToDetermineMultipleHits() throws Exception { - when(group.contains(any())).then(invocation -> - invocation.getArgumentAt(0, BibEntry.class).getField("author").contains("author1")); - assertEquals(2, group.numberOfHits(entries)); - } - - } diff --git a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java index 4d080aa1dfaf..193de02013e1 100644 --- a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java @@ -1,18 +1,31 @@ package net.sf.jabref.logic.groups; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.search.matchers.AndMatcher; import net.sf.jabref.logic.search.matchers.OrMatcher; +import net.sf.jabref.model.entry.BibEntry; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; public class GroupTreeNodeTest { + private List entries = new ArrayList<>(); + + @Before + public void setUp() throws Exception { + entries.add(new BibEntry().withField("author", "author1 and author2")); + entries.add(new BibEntry().withField("author", "author1")); + } + + /** * Gets the marked node in the following tree of explicit groups: * Root @@ -174,4 +187,47 @@ public void getSearchRuleForIncludingGroupReturnsGroupOrSubgroupAsMatcher() thro matcher.addRule(child.getGroup()); assertEquals(matcher, node.getSearchRule()); } + + @Test + public void numberOfHitsReturnsZeroForEmptyList() throws Exception { + assertEquals(0, getNodeInSimpleTree().numberOfHits(Collections.emptyList())); + } + + @Test + public void numberOfHitsMatchesOneEntry() throws Exception { + GroupTreeNode parent = getNodeInSimpleTree(); + GroupTreeNode node = parent.addSubgroup( + new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT)); + assertEquals(1, node.numberOfHits(entries)); + } + + @Test + public void numberOfHitsMatchesMultipleEntries() throws Exception { + GroupTreeNode parent = getNodeInSimpleTree(); + GroupTreeNode node = parent.addSubgroup( + new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.INDEPENDENT)); + assertEquals(2, node.numberOfHits(entries)); + } + + // Test for #1482 + @Test + public void numberOfHitsWorksForRefiningGroups() throws Exception { + GroupTreeNode grandParent = getNodeInSimpleTree(); + GroupTreeNode parent = grandParent.addSubgroup( + new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT)); + GroupTreeNode node = parent.addSubgroup( + new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.REFINING)); + assertEquals(1, node.numberOfHits(entries)); + } + + // Test for #1482 + @Test + public void numberOfHitsWorksForHierarchyOfIndependentGroups() throws Exception { + GroupTreeNode grandParent = getNodeInSimpleTree(); + GroupTreeNode parent = grandParent.addSubgroup( + new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT)); + GroupTreeNode node = parent.addSubgroup( + new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.INDEPENDENT)); + assertEquals(2, node.numberOfHits(entries)); + } } From e099d5edb511efadfd0ef3bd9d3cf08fad5e9d30 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 6 Jun 2016 22:13:23 +0200 Subject: [PATCH 141/268] Disable build abort when integrationTest fails --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 62ae3db4eff8..135d97810f1c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,10 @@ before_script: - psql -c 'create database jabref;' -U postgres script: - - ./gradlew check integrationTest + - ./gradlew check + # Integration tests currently often fail with "Process 'Gradle Test Executor 1' finished with non-zero exit value 137" + # They should run, but the result is ignored + - ./gradlew integrationTest --info || exit 0 after_script: # enable codecov report From 81399f0542d3757db01e470ce66632f34fe1f471 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 7 Jun 2016 18:27:21 +0200 Subject: [PATCH 142/268] Refactor placement of parsing and writing logic (#1453) * Move parsing to CustomEntryType * Add parse method to metadata * Add parse method to GroupTreeNode * Reuse FieldFormatterCleanups.parse method * Introduce or reuse parse methods * Introduce or rename some getAsString methods * Rename serialize to getAsString * Move serialization to CustomEntryType * Rename some getAsString methods --- .../java/net/sf/jabref/JabRefPreferences.java | 2 +- src/main/java/net/sf/jabref/MetaData.java | 32 +++++++++---------- .../sf/jabref/exporter/BibDatabaseWriter.java | 11 ++----- .../exporter/FieldFormatterCleanups.java | 4 +-- .../importer/fileformat/BibtexParser.java | 5 ++- .../jabref/logic/CustomEntryTypesManager.java | 18 ----------- .../jabref/logic/cleanup/CleanupPreset.java | 4 +-- .../jabref/logic/config/SaveOrderConfig.java | 8 +++-- .../sf/jabref/logic/groups/GroupTreeNode.java | 5 +++ .../sf/jabref/logic/groups/GroupsParser.java | 2 +- .../model/database/BibDatabaseMode.java | 10 ++++++ .../jabref/model/entry/CustomEntryType.java | 31 ++++++++++++++++++ src/test/java/net/sf/jabref/MetaDataTest.java | 4 +-- 13 files changed, 80 insertions(+), 56 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index dce46b1efa3e..dda85b404977 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -1387,7 +1387,7 @@ private static void insertCleanupPreset(Map storage, CleanupPres storage.put(CLEANUP_UPGRADE_EXTERNAL_LINKS, preset.isCleanUpUpgradeExternalLinks()); storage.put(CLEANUP_CONVERT_TO_BIBLATEX, preset.isConvertToBiblatex()); storage.put(CLEANUP_FIX_FILE_LINKS, preset.isFixFileLinks()); - storage.put(CLEANUP_FORMATTERS, convertListToString(preset.getFormatterCleanups().convertToString())); + storage.put(CLEANUP_FORMATTERS, convertListToString(preset.getFormatterCleanups().getAsStringList())); } } diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index 669a8293b0b6..61cc13e1b093 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -24,7 +24,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -36,7 +35,6 @@ import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.logic.groups.GroupTreeNode; -import net.sf.jabref.logic.groups.GroupsParser; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.AbstractLabelPattern; import net.sf.jabref.logic.labelpattern.DatabaseLabelPattern; @@ -79,7 +77,7 @@ public class MetaData implements Iterable { * must simply make sure the appropriate changes are reflected in the Vector * it has been passed. */ - public MetaData(Map inData) throws ParseException { + private MetaData(Map inData) throws ParseException { Objects.requireNonNull(inData); for (Map.Entry entry : inData.entrySet()) { @@ -96,11 +94,9 @@ public MetaData(Map inData) throws ParseException { } if (GROUPSTREE.equals(entry.getKey())) { putGroups(orderedData); - // the keys "groupsversion" and "groups" were used in JabRef versions around 1.3, we will not use them here + // the keys "groupsversion" and "groups" were used in JabRef versions around 1.3, we will not support them anymore } else if (SAVE_ACTIONS.equals(entry.getKey())) { - boolean enablementStatus = "enabled".equals(orderedData.get(0)); - String formatterString = orderedData.get(1); - setSaveActions(new FieldFormatterCleanups(enablementStatus, formatterString)); + setSaveActions(FieldFormatterCleanups.parse(orderedData)); } else { putData(entry.getKey(), orderedData); } @@ -114,10 +110,14 @@ public MetaData() { // No data } + public static MetaData parse(Map data) throws ParseException { + return new MetaData(data); + } + public Optional getSaveOrderConfig() { List storedSaveOrderConfig = getData(SAVE_ORDER_CONFIG); if (storedSaveOrderConfig != null) { - return Optional.of(new SaveOrderConfig(storedSaveOrderConfig)); + return Optional.of(SaveOrderConfig.parse(storedSaveOrderConfig)); } return Optional.empty(); } @@ -178,7 +178,7 @@ public void putData(String key, List orderedData) { */ private void putGroups(List orderedData) throws ParseException { try { - groupsRoot = GroupsParser.importGroups(orderedData); + groupsRoot = GroupTreeNode.parse(orderedData); } catch (ParseException e) { throw new ParseException(Localization.lang( "Group tree could not be parsed. If you save the BibTeX database, all groups will be lost."), e); @@ -299,9 +299,7 @@ public Optional getSaveActions() { if (this.getData(SAVE_ACTIONS) == null) { return Optional.empty(); } else { - boolean enablementStatus = "enabled".equals(this.getData(SAVE_ACTIONS).get(0)); - String formatterString = this.getData(SAVE_ACTIONS).get(1); - return Optional.of(new FieldFormatterCleanups(enablementStatus, formatterString)); + return Optional.of(FieldFormatterCleanups.parse(getData(SAVE_ACTIONS))); } } @@ -310,7 +308,7 @@ public Optional getMode() { if ((data == null) || data.isEmpty()) { return Optional.empty(); } - return Optional.of(BibDatabaseMode.valueOf(data.get(0).toUpperCase(Locale.ENGLISH))); + return Optional.of(BibDatabaseMode.parse(data.get(0))); } public boolean isProtected() { @@ -352,7 +350,7 @@ public Optional getUserFileDirectory(String user) { /** * Writes all data in the format . */ - public Map serialize() { + public Map getAsStringMap() { Map serializedMetaData = new TreeMap<>(); @@ -394,17 +392,17 @@ public Map serialize() { } public void setSaveActions(FieldFormatterCleanups saveActions) { - List actionsSerialized = saveActions.convertToString(); + List actionsSerialized = saveActions.getAsStringList(); putData(SAVE_ACTIONS, actionsSerialized); } public void setSaveOrderConfig(SaveOrderConfig saveOrderConfig) { - List serialized = saveOrderConfig.getConfigurationList(); + List serialized = saveOrderConfig.getAsStringList(); putData(SAVE_ORDER_CONFIG, serialized); } public void setMode(BibDatabaseMode mode) { - putData(DATABASE_TYPE, Collections.singletonList(mode.getFormattedName().toLowerCase(Locale.ENGLISH))); + putData(DATABASE_TYPE, Collections.singletonList(mode.getAsString())); } public void markAsProtected() { diff --git a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java index a735aa410882..72925e078ffd 100644 --- a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java @@ -281,7 +281,7 @@ private void writeMetaData(Writer out, MetaData metaData) throws IOException { return; } - Map serializedMetaData = metaData.serialize(); + Map serializedMetaData = metaData.getAsStringMap(); for(Map.Entry metaItem : serializedMetaData.entrySet()) { @@ -392,13 +392,8 @@ private void writeTypeDefinitions(Writer writer, Map types) t CustomEntryType customType = (CustomEntryType) type; writer.write(Globals.NEWLINE); writer.write(COMMENT_PREFIX + "{"); - writer.write(CustomEntryType.ENTRYTYPE_FLAG); - writer.write(customType.getName()); - writer.write(": req["); - writer.write(customType.getRequiredFieldsString()); - writer.write("] opt["); - writer.write(String.join(";", customType.getOptionalFields())); - writer.write("]}"); + writer.write(customType.getAsString()); + writer.write("}"); writer.write(Globals.NEWLINE); } } diff --git a/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java b/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java index 10cdacdbe7df..52d3d7ee70aa 100644 --- a/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java +++ b/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java @@ -198,7 +198,7 @@ private static String getMetaDataString(List actionList) return result.toString(); } - public List convertToString() { + public List getAsStringList() { List stringRepresentation = new ArrayList<>(); if (enabled) { @@ -212,7 +212,7 @@ public List convertToString() { return stringRepresentation; } - public static FieldFormatterCleanups parseFromString(List formatterMetaList) { + public static FieldFormatterCleanups parse(List formatterMetaList) { if (formatterMetaList != null && formatterMetaList.size() >= 2) { boolean enablementStatus = "enabled".equals(formatterMetaList.get(0)); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 7369c9020ea0..f4c78b0c2f0a 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -30,7 +30,6 @@ import net.sf.jabref.MetaData; import net.sf.jabref.importer.ParserResult; -import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.bibtex.FieldContentParser; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; @@ -196,7 +195,7 @@ private ParserResult parseFileContent() throws IOException { // Instantiate meta data: try { - parserResult.setMetaData(new MetaData(meta)); + parserResult.setMetaData(MetaData.parse(meta)); } catch (ParseException exception) { parserResult.addWarning(exception.getLocalizedMessage()); } @@ -281,7 +280,7 @@ private void parseJabRefComment(Map meta) throws IOException { .equals(CustomEntryType.ENTRYTYPE_FLAG)) { // A custom entry type can also be stored in a // "@comment" - CustomEntryType typ = CustomEntryTypesManager.parseEntryType(comment); + CustomEntryType typ = CustomEntryType.parse(comment); if(typ == null) { parserResult.addWarning(Localization.lang("Ill-formed entrytype comment in bib file") + ": " + comment); diff --git a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java b/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java index 3fdb3e82a074..f26f17bcabe3 100644 --- a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java +++ b/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java @@ -50,22 +50,4 @@ public static void saveCustomEntryTypes(JabRefPreferences prefs) { prefs.purgeCustomEntryTypes(number); } - public static CustomEntryType parseEntryType(String comment) { - String rest = comment.substring(CustomEntryType.ENTRYTYPE_FLAG.length()); - int indexEndOfName = rest.indexOf(':'); - if(indexEndOfName < 0) { - return null; - } - String fieldsDescription = rest.substring(indexEndOfName + 2); - - int indexEndOfRequiredFields = fieldsDescription.indexOf(']'); - int indexEndOfOptionalFields = fieldsDescription.indexOf(']', indexEndOfRequiredFields + 1); - if (indexEndOfRequiredFields < 4 || indexEndOfOptionalFields < indexEndOfRequiredFields + 6) { - return null; - } - String name = rest.substring(0, indexEndOfName); - String reqFields = fieldsDescription.substring(4, indexEndOfRequiredFields); - String optFields = fieldsDescription.substring(indexEndOfRequiredFields + 6, indexEndOfOptionalFields); - return new CustomEntryType(name, reqFields, optFields); - } } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java index fe7ac7ac2a64..b0ed7b6fa3d5 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java @@ -74,7 +74,7 @@ public static CleanupPreset loadFromPreferences(JabRefPreferences preferences) { activeJobs.add(CleanupStep.FIX_FILE_LINKS); } - FieldFormatterCleanups formatterCleanups = FieldFormatterCleanups.parseFromString( + FieldFormatterCleanups formatterCleanups = FieldFormatterCleanups.parse( preferences.getStringList(JabRefPreferences.CLEANUP_FORMATTERS)); return new CleanupPreset(activeJobs, formatterCleanups); @@ -124,7 +124,7 @@ public void storeInPreferences(JabRefPreferences preferences) { preferences.putBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBLATEX, isActive(CleanupStep.CONVERT_TO_BIBLATEX)); preferences.putBoolean(JabRefPreferences.CLEANUP_FIX_FILE_LINKS, isActive(CleanupStep.FIX_FILE_LINKS)); - preferences.putStringList(JabRefPreferences.CLEANUP_FORMATTERS, formatterCleanups.convertToString()); + preferences.putStringList(JabRefPreferences.CLEANUP_FORMATTERS, formatterCleanups.getAsStringList()); } private Boolean isActive(CleanupStep step) { diff --git a/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java b/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java index 7c5efb06ef36..e0c84911e809 100644 --- a/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java +++ b/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java @@ -19,6 +19,10 @@ public class SaveOrderConfig { // quick hack for outside modifications public final SortCriterion[] sortCriteria = new SortCriterion[3]; + public static SaveOrderConfig parse(List orderedData) { + return new SaveOrderConfig(orderedData); + } + public static class SortCriterion { public String field; @@ -112,7 +116,7 @@ public String toString() { return sb.toString(); } - public SaveOrderConfig(List data) { + private SaveOrderConfig(List data) { Objects.requireNonNull(data); if (data.isEmpty()) { @@ -188,7 +192,7 @@ public void storeAsExportSaveOrderInPreferences(JabRefPreferences preferences) { /** * Outputs the current configuration to be consumed later by the constructor */ - public List getConfigurationList() { + public List getAsStringList() { List res = new ArrayList<>(7); if (saveInOriginalOrder) { res.add("original"); diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java index 3cae6ac49101..d354e4c9c908 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Objects; +import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.search.SearchMatcher; import net.sf.jabref.logic.search.matchers.MatcherSet; import net.sf.jabref.logic.search.matchers.MatcherSets; @@ -213,4 +214,8 @@ public String toString() { public GroupTreeNode copyNode() { return new GroupTreeNode(group); } + + public static GroupTreeNode parse(List orderedData) throws ParseException { + return GroupsParser.importGroups(orderedData); + } } diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java b/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java index c3f4a83afbc8..b19a3873365e 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java @@ -25,7 +25,7 @@ /** * Converts string representation of groups to a parsed {@link GroupTreeNode}. */ -public class GroupsParser { +class GroupsParser { public static GroupTreeNode importGroups(List orderedData) throws ParseException { GroupTreeNode cursor = null; diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabaseMode.java b/src/main/java/net/sf/jabref/model/database/BibDatabaseMode.java index 277307b9c7ff..54b402dc3d8a 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabaseMode.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabaseMode.java @@ -1,5 +1,7 @@ package net.sf.jabref.model.database; +import java.util.Locale; + public enum BibDatabaseMode { BIBTEX, BIBLATEX; @@ -23,4 +25,12 @@ public BibDatabaseMode getOppositeMode() { public static BibDatabaseMode fromPreference(boolean isBibLatex) { return isBibLatex ? BIBLATEX : BIBTEX; } + + public static BibDatabaseMode parse(String data) { + return BibDatabaseMode.valueOf(data.toUpperCase(Locale.ENGLISH)); + } + + public String getAsString() { + return getFormattedName().toLowerCase(Locale.ENGLISH); + } } diff --git a/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java b/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java index b7929f628bd7..0e25356ba3c4 100644 --- a/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java +++ b/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java @@ -51,6 +51,25 @@ public CustomEntryType(String name, String required, String optional) { this(name, Arrays.asList(required.split(";")), Arrays.asList(optional.split(";"))); } + public static CustomEntryType parse(String comment) { + String rest = comment.substring(ENTRYTYPE_FLAG.length()); + int indexEndOfName = rest.indexOf(':'); + if(indexEndOfName < 0) { + return null; + } + String fieldsDescription = rest.substring(indexEndOfName + 2); + + int indexEndOfRequiredFields = fieldsDescription.indexOf(']'); + int indexEndOfOptionalFields = fieldsDescription.indexOf(']', indexEndOfRequiredFields + 1); + if (indexEndOfRequiredFields < 4 || indexEndOfOptionalFields < indexEndOfRequiredFields + 6) { + return null; + } + String name = rest.substring(0, indexEndOfName); + String reqFields = fieldsDescription.substring(4, indexEndOfRequiredFields); + String optFields = fieldsDescription.substring(indexEndOfRequiredFields + 6, indexEndOfOptionalFields); + return new CustomEntryType(name, reqFields, optFields); + } + @Override public int compareTo(EntryType o) { return getName().compareTo(o.getName()); @@ -105,4 +124,16 @@ public String getRequiredFieldsString() { public int hashCode() { return super.hashCode(); } + + public String getAsString() { + StringBuilder builder = new StringBuilder(); + builder.append(ENTRYTYPE_FLAG); + builder.append(getName()); + builder.append(": req["); + builder.append(getRequiredFieldsString()); + builder.append("] opt["); + builder.append(String.join(";", getOptionalFields())); + builder.append("]"); + return builder.toString(); + } } diff --git a/src/test/java/net/sf/jabref/MetaDataTest.java b/src/test/java/net/sf/jabref/MetaDataTest.java index 6ed59e9a7a52..81fb660887d8 100644 --- a/src/test/java/net/sf/jabref/MetaDataTest.java +++ b/src/test/java/net/sf/jabref/MetaDataTest.java @@ -25,7 +25,7 @@ public void setUp() { @Test public void serializeNewMetadataReturnsEmptyMap() throws Exception { - assertEquals(Collections.emptyMap(), metaData.serialize()); + assertEquals(Collections.emptyMap(), metaData.getAsStringMap()); } @Test @@ -37,6 +37,6 @@ public void serializeSingleSaveAction() { Map expectedSerialization = new TreeMap<>(); expectedSerialization.put("saveActions", "enabled;" + Globals.NEWLINE + "title[lower_case]" + Globals.NEWLINE + ";"); - assertEquals(expectedSerialization, metaData.serialize()); + assertEquals(expectedSerialization, metaData.getAsStringMap()); } } From b423189a39b957ddb3aa34a3cc769195cb0654d4 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Thu, 9 Jun 2016 10:15:36 +0200 Subject: [PATCH 143/268] Fixes #1485 Export shorttitle as standard field --- CHANGELOG.md | 1 + .../java/net/sf/jabref/logic/msbib/MSBibMapping.java | 4 ++-- .../net/sf/jabref/exporter/MsBibExportFormatTest1.bib | 4 ++-- .../resources/net/sf/jabref/exporter/MsBibShorttitle.bib | 4 ++++ .../resources/net/sf/jabref/exporter/MsBibShorttitle.xml | 9 +++++++++ .../sf/jabref/importer/fileformat/MsBibImporterTest2.bib | 2 +- 6 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.bib create mode 100644 src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index b73aebea0e16..3f5a0eb91a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed +- [#1485](https://github.com/JabRef/jabref/issues/1485) Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography ### Fixed - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java index f9561b37e5b6..3b6b63e69469 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java @@ -34,7 +34,7 @@ public class MSBibMapping { bibtexToMSBib.put("institution", "Institution"); bibtexToMSBib.put("doi", "DOI"); bibtexToMSBib.put("url", "URL"); - // BibTeX only fields + // BibTeX/Biblatex only fields bibtexToMSBib.put("series", BIBTEX_PREFIX + "Series"); bibtexToMSBib.put("abstract", BIBTEX_PREFIX + "Abstract"); bibtexToMSBib.put("keywords", BIBTEX_PREFIX + "KeyWords"); @@ -47,8 +47,8 @@ public class MSBibMapping { bibtexToMSBib.put("size", BIBTEX_PREFIX + "Size"); bibtexToMSBib.put("intype", BIBTEX_PREFIX + "InType"); bibtexToMSBib.put("paper", BIBTEX_PREFIX + "Paper"); + bibtexToMSBib.put("shorttitle", "ShortTitle"); // MSBib only fields - bibtexToMSBib.put(MSBIB_PREFIX + "shorttitle", "ShortTitle"); bibtexToMSBib.put(MSBIB_PREFIX + "numberofvolume", "NumberVolumes"); bibtexToMSBib.put(MSBIB_PREFIX + "periodical", "PeriodicalTitle"); //bibtexToMSBib.put(MSBIB_PREFIX + "day", "Day"); diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib index 3d321249f664..7f853424f3a5 100644 --- a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib +++ b/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib @@ -12,11 +12,12 @@ @unpublished{ crossref = {cross}, edition = {10}, howpublished = {how}, + shorttitle = {Turing}, isbn = {‎978-3-16-148410-0}, intype = {intype}, paper = {paper}, editor = {Alfred}, - sourceType ={Interview}, + sourceType ={Interview}, institution = {Institution}, msbib-abbreviatedcasenumber = {abb}, msbib-accessed = {12.10.2015}, @@ -32,7 +33,6 @@ @unpublished{ msbib-recordingnumber = {record}, msbib-reporter = {rep}, msbib-periodical = {peri}, - msbib-shorttitle = {Turing}, msbib-station = {stat}, msbib-theater = {th}, msbib-type = {type}, diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.bib b/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.bib new file mode 100644 index 000000000000..d7d970da45a8 --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.bib @@ -0,0 +1,4 @@ +@Article{, + shorttitle = {Title} +} + diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.xml b/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.xml new file mode 100644 index 000000000000..195051eef8bb --- /dev/null +++ b/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.xml @@ -0,0 +1,9 @@ + + + +JournalArticle +Title + +article + + diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib index 1907e883d4bb..71352ffe0ab9 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MsBibImporterTest2.bib @@ -14,6 +14,7 @@ @Article{ language = {english}, howpublished = {how}, institution = {Institution}, + shorttitle = {Turing}, msbib-abbreviatedcasenumber = {abb}, msbib-accessed = {July 3, 2010}, msbib-broadcaster = {broad}, @@ -26,7 +27,6 @@ @Article{ msbib-productioncompany = {produktion}, msbib-recordingnumber = {record}, msbib-reporter = {rep}, - msbib-shorttitle = {Turing}, msbib-station = {stat}, msbib-theater = {th}, msbib-type = {type}, From 3380c31aad55b48108917b5080c180a926d423a6 Mon Sep 17 00:00:00 2001 From: matthiasgeiger Date: Thu, 9 Jun 2016 14:49:06 +0200 Subject: [PATCH 144/268] removed small logo integrated in svg and use real square as background --- .../resources/images/icons/JabRef-icon.svg | 102 ++++++------------ 1 file changed, 33 insertions(+), 69 deletions(-) diff --git a/src/main/resources/images/icons/JabRef-icon.svg b/src/main/resources/images/icons/JabRef-icon.svg index 120485811a21..e5988a225628 100644 --- a/src/main/resources/images/icons/JabRef-icon.svg +++ b/src/main/resources/images/icons/JabRef-icon.svg @@ -1,21 +1,22 @@ + + inkscape:version="0.91 r13725" + sodipodi:docname="JabRef-icon.svg" + version="1.1"> - - + inkscape:window-width="1920" + inkscape:window-height="1137" + inkscape:window-x="1912" + inkscape:window-y="-8" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> @@ -153,55 +139,33 @@ image/svg+xml + + id="layer1" + transform="translate(-10.717734,-89.63427)"> + y="89.63427" /> + sodipodi:nodetypes="cccscssc" + inkscape:connector-curvature="0" /> - - - + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" /> From 061008678487459692c08b43187e3fa4d67b78f8 Mon Sep 17 00:00:00 2001 From: Christoph Hochreiner Date: Thu, 9 Jun 2016 15:29:36 +0200 Subject: [PATCH 145/268] Fixes #1481 Icon image for OSX broken (#1488) --- CHANGELOG.md | 2 ++ src/main/resources/icons/jabref.icns | Bin 119529 -> 126105 bytes 2 files changed, 2 insertions(+) mode change 100644 => 100755 src/main/resources/icons/jabref.icns diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f5a0eb91a56..5b5f3dfc23aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - Fixed [#1476](https://github.com/JabRef/jabref/issues/1476): NPE when importing from SQL DB because of missing DatabaseMode +- Fixed [#1481](https://github.com/JabRef/jabref/issues/1481): Mac OS X binary seems broken for JabRef 3.4 release + ### Removed diff --git a/src/main/resources/icons/jabref.icns b/src/main/resources/icons/jabref.icns old mode 100644 new mode 100755 index 2e0615d160ec6d763cc2412600263886e94d4746..fb71592d825f3f36893d2721540a4ea6aa6af79a GIT binary patch literal 126105 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 U58Avm58Q4OAbzpI|99hm0ic3masU7T literal 119529 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

    ^AyeT-*tyZtd< zxW`6Ux}ojf;whDiyQfYmX1{MLxG-C_WOW2}aJp)1$Y*_`>iyflzMcP)rFM2pXWN=* znl?My{5+neO`cG2x00y(bMdR=Z(r};l_MQ?wnJgDs&8+X5s})rp!0Z>>Z#SO`~0ps zu(kT1Y%w`JHh%rhDqWpDL0w;zKF+;=x?ScM>XKUU#3KB+pJ(2y!t|7?6>caqd5 zZnCRab&qp!dfBhpk4|^Z={{3la!lj8{MP8VOI{T>R@p4p$HtE{FKpJKw^(_|NH_hN zI_vXng%!Cs&p%pu@LOB$82({#xroq(UpGW#B~;HjT%PfC;IiKeXB8!4QKV8K1LeStLG{onSw{`zwz2N%%URdXP3ahsWZ=)JT?-~ zn03-X#r-Gm`upCGugXX-I+8Gv^PD(W(>z8?VPDdx9nTu#Pi9ozvs`@O+LN6*PYq7% z@}?c>+jXT^UZJq9;_%hIe{aY1%o`Ik7Ooc&NigV<`uWJo$=9xBu&Se$^z%&m>2Wrf zINa_zi(+?1>RvYteVp^n*@c{uyW_$y{%fw$wl(SxKXE-Kn3r;~pC{xU;`pzr{C(Be zJ(CG`umq-MP@7xjrllfJ{gz*$G|qKRw%GO6@ynE~ss66BzcpB&);{ycAJ<+jPI7Qe zbF!7{xiEjqGslDFJI(IjFFYM}{Ti?0&QIIK#_#f+5gNEm!7<-wyTYmizpQxke#^!A&zKS18)4TAn)RknlorYQXlEt(vtbl0;7*m`Rju*WB~DsPC`BM@wEw`icDM zZ2u(a^QQtb8@t3#opkQk31imvcpg{yO5iZrN*>zx-vZ1=)xW41QqEk)8P4<4BZJ|RX>YhEb;7{)Ohco;a z>vSijR;+b6cXIAo7U!qVuk2fvX76jV8=cf6!)n4gRLLgG^8CO0W~8Tn*DDTZ%i0%q z@X{mpO45zWIct5^%q66?-&EX~yzT6_&}ilFFXB`dWE4=*xj7PQ!6wl~*_8p>)yMmN zTGMAGa6kN^VOC`>bw_c3`mCiv8;a=PesPX}95-t}$@y93Vy;^B%AmhuCv3Q)ZnQ!3 z-i4U(jokb3*KRn-iThz~(+_+;uljfw-h1BRQd6S2&#b#@-mp6u{bvCr7q5WTg0W=S|D? zr*`CBpl%0c$L7g4#Fg*rdSbrfwAwNCJ!5V@p_AW=Chk6-KHKBjtvBk13mz*;zPa(M zV)(52Vs$NMpL=H3UElF--gwXP0q?aorK~XcWW+ja+7?vWo$&C{?Q6|rRBdKH=FIm$ z6kY$w=xrfBf3e-;uS=es2s~i^B(BESaI4#{2mc(@e@#8k|7pYdu|$%RzP`*6(W6$J zQ*)Ph7H*oAXZcr+(XVb2y!oqkPhNQc_my5d*N)TY+um5P%4N~LE{$aaOR1cv_t_W3 z`xBcJtER5H@-6G@*%>EugOt zeP&^DndtNx#cS*WHsnY>*miKsi?%Usk8StMm7LhM{H<>Qv9LXF??U$n-&In8GNk?nt0-Svtb=X_!3?xk_gs+L~-c$!tW zPVk#7F?RDa>d1*be;)q0&qZmsjY5&b)_>-kCx-FGbpBp+Hbf;d{Li27R?Jtae1G`D z&Xn}iJ`~P=KmJ?TAy;{1&zP;|n+CL6Yk=}6Ly0ODO z+r7r?)5^)`UW`qA@<*q-dV=3a_N;-06-5VkwkwAvTLjK%wx6?WR-62)np2tbH9t={ z_xR!TBSBZ$d9$Z2UEsCwXJ#>DV3en@9BH z=#GTaZVwe>gYvgUPd|8$JGbPtyF=b`zgw$q4yjI=IP+T4F146D*NEh+c{jB~-XA`; zrEAVI@xp=SZqGZL!;Y3V-?{ZHBCBMa)bw?hd)F_To0;tEzSS{h_c5bqcjso_dH5wM z)Hhk~);Y~d^Uc@39Ur&oer$p9R`-r=yAJJscy3=8~8TMrYWu#bKX3`<{2l? z!}@i@PaWJ}iXZPks(Uy<_U!%Lsq;Fj9*~DobA{KGmFSOPt2e-Cw_>1)3s+yK8<@`AQt;k$b!fbU|ZFE-HOvPO@EGJIe z)4gjznXMC(&~Eb9;`E&+)%mk`_gRK?=U4XzeanA$RZ=0s@zc8I$&x;6E7xC?{67Fk zK)An^CgANBUnbJnQl%a+jh2sp8M>3{s5qwIxGW70p@U&7K4_d@5G!IqsQ+Sea54iZ z-GNR%Vn0n@>O*~)7PXt4ab~ZR5tcb9vkMDU|54X&WVbN`5_+%ZGA8t9qEG2Yu3vyJ z6R!vs{vV!Sw>DUCJ*vr21mL%kz@I-)L$1U+QhRbG&EEi(i-@P zs98%93=Vd(p#KHouOUifhy&g7c}neoLrRHNLSuXo<8V=Joi2-zxqQED$t6HHU&ti5 z^P$0rr944}H%(s#<<8p&gIlLutPg!}S(5R&l-*`-#(n6?1ChUv4_C_k{DXynua(+% z(XppL5JAO`fe3O*XG{h4_PrOuxvdp!S@tixP9CWV(Uba1{I$TVsx1L8#ZLpHujyUQ zE?y&iDr3m&@Rj%E+@MNspIdj^oU+3c8KE&6q;XtOtmpxP#y`}#zJxei8U`KaDUrhS z6ikCkZtF{Tg#>EkuKT(V$gcDZ3#;S-$=SKrMyjUPK$?8kNzD8Qi#@Iy6lVHEI4{`S z7&+`>i|t8IV72cR)i;z?`5nno?N*2~C1HNsjvc59CMD3c)EE6jkKDyK>lGPCLoZ3N z<9tBJ^YtCI397roYez%zYBh#b;kc``M5)AE41Kf zlqY00tF+I3XmWDcfB1eIjZ@~9Q!i4rqbN8SpiP(3tvgi(y|J!GH2SH9>x`e*Dol*6 zZ^&Ees~VN3q>}0SBy)m|L1&)?H7kp-;WV)%;FA+5Z*#2?Ti*)R3CxDRx>Q=DeS`jmUZ5&Q z&Y6*B$IlgF$tSR9cf5qOeG;a8mOONF+nPeP^e4(Nv6G zWBO##ma^k8{4r=V9iDOO_Di`4R<1cR;o&DfTR^7&bk{0xI7qV0Vw+xB$Q{j#r%z3c zZcgD5O|2|cU$O6Sl^Adgy`v+Wc8nVkc!zy(wY%Lk#AsIs9O7Q<)-@Gzr za@5?geQs>a`-MPk2_t2UZLpuSYD939nkry-3q{yejJ_QsFnFc$LD}UGE@6}jqXD}U z1C)~j1wv*b)fhnGj1#t$8 zM|<{!U*{(XKY|sr>!h{Skk4}Xh7(r^kPTE2%#fwyy}Qt`_5&7qeRAMJpS zQ1mq;=q3!p`1+a-Lr6D?4h&d8s&_vSQZ&3c4pfb}@Y5g1+u4kLy@W&U?994re0LdJ z;VMfcxso41h9@6;kzK-Gsvy-!hp})C^XHnEG{8tjHY2SQw)xCLDWJf zoGzZBn;3UR!B$*+1t4us;mC35QflN66-7Qd9$C$B??GxefP{KCm*3hUJb9Ab#(#{} z8bey9`U(e2^v&Zl67DiQn4I|R;yKgqSK2Klc8H_h#qicZL^KtdKfmw9o{}8TRk2RX zeY3y;G1wOEQO)vs*Ye}_B&(7InDwq5%gFA}{=?HeQ|d8hnPNvKG9L}G8v#HX5e3?l zKBX(YMgKWr7^`eJJ_%q+$Oy(*z#Vtxkz6>?9XfRzqkFizi|jxWoK3}Y_N>4<#D4$~_7)wTJ7aFq z1-35Hn5Yq7?F_b!`Utd%K(^`T%0;ctMHUeqySbMUoj=&y=Pv7Bnc_Z)K1Rn<%@1|m zi;%MOa3R(%l`{^o9b|eOMxJ=N^hL%roRJ4j-W%->`1@YBML`LiHky_ma^wTFz)Ip~ zmnDdMWgAbxVD%I&Qj5iR5~DKaPMcJ${N}XU+n34x zq2DIn0{cnotPbyi!x-$IRmB!`yu1@izt7}$u}=GKVNOrR%AX-Mld98U)y?@JgX)mO z8muO0nHDw07v=*;RhtF8gFQvz{f!;qL#6w4*w<_}${Ya3PO1pC}x`cJ9@#2bL5@25K^6?yp3 zVY{txnA*s30gU#K9k?uA&~Bk221eYXDmfi{3cYXxYF|mED|_R|m@wFPcZmrj7S^M&vP993XG7kvoCK zEnYuj9D_0K=N6NjZ8o$eM>i5a=!2J!tbZ`IbOd6Ei#0RBPXQ%QR;97ac$@x zC@e1E?3gF#m)V|qM^@$0=*W!E4UYK#{3v^muzVfdxoOI zyFG`aowimJ+F(<`z0x^+edBiAD%{o^dQDkRAMq+r66uwR9_e0NRrwZroR8y|dq%}K z<9S=IE<;EOk@G))2c6AMijLHQr=1~-4MeECLZaQuD97JO1gVrm@$m83e?b(v71&V< zUGX1Z^e`Uslj1eK^!T{xT0Xh@0_1*#c4Vfv=p7CpZE?(&SiV`>++$+>gkM6D_ByfV zYO&%FLvzk3ZaX}{^#ml4Y)li=!3bXuup%4j$Z@7fojaU**dt8`@If>e8%dJA=`#R{ zq0}8DP48ql^Fso?Ne#N=>bn+-}vA1`Nu zpa#VI&&6`y)rF6{1`es)mLrJ;qDM-np^0a`fjBl_N|YTtCwz4U2RSl#a0CuO5T*%M zd%^rHz3$KX!TO~!yuE@|S!L`COY^Cydivyj+#dQZC1@|P0~6g}%@6l;VfV*(=GKl# zM#8wWB}}a_V3Z|HX5Vgp{AhH|DUu)4JrN!k8y+@P(G^Xus{e7Y$|3L!)P(IRC5Bra0(;~TX;25%ngzQ` zyebk{Beq%w2_`ib%z6}5ZB)4gJd*gW8;*LAU~3?f>T`@DJ?t$q4-8lD=$x6mwa%>` zw#XFBRHzIf9l_0QCz6t1y_rVezGo={7H7Y=n=}GvQzKNAyl)xtGpUtkRv;XBXEEF? z$RdkBk-*gBM)0!j&DUYvaV;Eygu|UceBPZi~D*G4l)d!ZR>I*+XJjDM(Q5b zsdV8RYsKxLZ=i)4LTPty(|?H9b?g{5Nz4^l{fzNKWmtm!(r4+$JssKjL`K_=ovt|* z?iy0rbTS6!Lf4)v1oHQ|4vqCr9swnxY+TM)Y(D2U^A_5-uJ4QE8;9+ZHSmX{yh<8a zjrIl#+r}WSgn-3vnWqao(vQdm-OXS{`U0yASld6e#zp|365E4Wu_UkP59AUq#&nvs z_K2W2@*Xgk?9-_8(%cg}oUQIg5l_MFbaDHncgbZ%tnWt8nHp7TATg?VsQ0zA z>bg$E8DqXdtphkGM^hdoqj)20kU;`M_@pYE;bcZP!t5%J+ah}M~{N;tC&PF58Hf1sf~r{ zkRBzau6}X-PH0+5? zdYj=3fR&b<{g21eubxz%D*(gIme0O&uBS`fF0Pj2`qP_A28N#R=EFk@sxhJ#366wF z*;1D^Qu+k|jR&DIodsCOb3uVNd`QCiDEf%1pVYF^p)HR_HJoFkUPB!n@BvH7-*YYj zMUjL?UGUc|On(-47k|gw*5rM?Wkc=jXu{lv#&~PRDUU#Dx8Zkx(c~wi@YGO=+!j~N z!Vb0UMKIM%#f9DRpC(3Rr?{x^C4yZ^rYB|Rjn{#xfmQ}iTCqEQZGAvV9b=A=f~+l_ z%C1Y&B)1e|=o@^TqIavY3u=KDsTyurN32t?cr_4xJ`T)KSgEeV8ZH^1ACcI!;>=(oMfM~7S@J1sI6ml+O- zU5ZkA;&ANM5Xg0eu_uf_Nd!8`q*GNbxma~3F=>v89d$k*ud=UB(lbJJD3??AQF zA9C?ex_7yXdn+XK5aVB*rJbY!cqQb>E2(`?sho3@ZS7W&)*G7zGZ!5n41x3|n~5Vm z)p5SRq`L_x!Q;NXUypMtX8}X6A{}X5as4n0z!Y=RAX=h? z4BtTyQomhK&Mf-&UT^2hI~q@kM>*oEI5?$xO_)xfCtBR26xS3Y8$(dJH0pI34X)+` zYJ9hZocY!k-Vz3JmfiXdUL7d-EU~!XfIpxI*XN#hefNWw2uH}k|2A9S3Fq-u+{}^u zn+%{iq#B08+HkQz5JvPuR}i< zIY@HW#`5GEv=%&pP3`{P-BhpgBpcGF=p0_vlQzNzCWi5G8NUl*aLf%Ti92Sp)WBaf zopEV!HjnNc`l{&*rh@=S6a(B@8 z0brzf3&RT_lc9!5qK-#VF4>q$ckvlGpohY^i4h|YC_@}{v3z&{QZPXikZ#KTEU_n^E7| zbi7_N$UQJCz7n#u0C3=!wfnnY{a5C#B@k9eUX;py_fB;W+XTr@4*+oFh z7cF-()YL}qwLwAJ$?W{#N}vc1>L5li6RmsLG!tilg^gxDuz*4lwPkB(TL0r-;d z1~M@?gD#!Z;&C z>I3jOcimSmQ38~JqLdA@yrZWeOc$DOblkz@L@ay_1tu6YuDo{3%|(VSI>EqWnA@yP zu7vl`+je18Pl1a_YYhPCQb9mC(Kw_L6}gtG9L3~Js&c!=uhWbA!r2N2=wS`LGsWiS zE)h^qRDdOmD0dF}=kq9jE1}sLcgtX=YxNI)_?Nrl@l0MlNjBb6wWNdagKSZ&+O~{v z2obvicr`bg@f3KB#_R9T=vKNqp=-0iX{|nHDG6olb|MO$>fn9v?#@>WVy$K?>2*Bs zHU?d^mDQ{$0Ywr2WG@D=1q{D_`72_NCCucEC#{*Mkm z$q$$)Dh6<|N`QdZ)%Qc)tAQeZ(Sv4+HXq!em`*La(;i9BMbn?%A3lj^pw zm^NXss^2cTsQHi8vmgBI^v2H_)y!rp85M#}!lJjsin)E7Fz!i8miD@V(ofgMFM9+= zSqj(Rf`+k>JjdJx5&OJX0kCh^?7>nN3sd#uD2Gf2at?2~CHX>5q2aCKMshv5Xp;;@ zcPMKBW+(|ROr~m!@qdfh>i4Fo=S}%?)T|)uw$4y-p1M|yvY!UCpbU0~j%|#ShQf;g zZnj`v%c~%Z!3VJZn`APKW+hwJn8gDwwq%IFUdvV5N<@6xddZmX|M8 zVfc?R2Nbt6rVar41j$C&^D$Vp(Mncyjg8nU=E<5jE9O#Ea&>qLXjEM$Dg&l)_rYtl zZe0Gf8+~cW4-$qP^5v~6hk)bu?Fa4IAKSRUw`8&Vb_4e8x9!>6>e!4wZo7Wngubnd zzO8)Y1J_+Pv*c=dk=`OotUB?$Xy-^Sge76bQQ&ZK*EDBtb_akv${IketTR?Coz&Gy z>382$QW{SYxeAl!OftG?#>Y_>7J$<-%TmXK4A~ev%5)@X-XBXjl|dbDjzfr+(n)zSLbHbx`;~kCBB`h@kIrU_$o6oGbyU3$A;0U3bU}gc} zgbCpGut`b*3~!n~x1$FN+S29D$7v(Br5pD|$`~gs6_>NBq8eN93z7;emWtc8ooOek z2`3y3uh3)v37yCI03sKS#epF0eJBWF$?NhXXM8ov^g>q!He^CTL+v?rT-CRCVSsNJ zwn2M|B#FgZE7~lcl-)^iPy6f%fdDFOshxoNK?&_oa_FB2TQ|rkaOY6oWw*!-n~{O1 zY*BkH@qoN2%O4&5&y+ILd~;PZjTa_kqh*yRbbHTQV z&v}CL63sEv4rldi`3+GDf5^44U=Qru*0ll5FXtg7rms|kybO;kRzMbZ=GR5%!tSca z*BGt=*bU(Xo$%_H#)A%#vX^E}@wy9lbB2nIkY8O|qNhZW5byeUQ=1|GxXUJ9( zEl>aIw_KAfsCu02pA`26AAA@78jF{5B@uv!6G7x&a#%8)IDJsfa5m9l*y&IrH~SY zL3C5lh?CO9c5aVB6`dU_GOuu_Mp2 z%YyAFowB#puNT8!Bl^rUjhcuC0vc0^?NX6>yo0pF4L8~nPXhY2ki?86aw%`c*Tb1I zsFqe3L75L_iw?PpoBUE#gmcC9@Jj-b;cV$Td$LRy)1|&+Ydjyc{JTXQ@L5^w3y=AS z!ZW2^L_Ok**p2-H&U{7-2^XJj1#XV$`%ddI>=1uO=&`@%iRX!dUE!tnyQO>xMz#xC zii-fccuIX3%y!;o45@?nd0Jr7SN{qc2$m}C7?K&epors7TTqFNE>)h{KBJ^lVBC_5 zZKj}_*&4t~Nl=~vx-l#)ZZnSg1ED_I{=Pi9u?kcX+lVf8`^KN^&JjkDM*;N1p7Wrc zTCY4NQYaN)QsT=(o~lqJDL6-e?LpByk!k%G>-&2KUVvkc0~ML68mnM-)2*mt zb_s={dF1K|K9n-rS$Xn{^@C+PeJZS+`IthGNZ{DxghWA5m4l1yso+m}+cWOVG?ujZ z(J&+fp5xE@I_AgVQHzNJB z9$RbD@+6MQO}W-WqV|I?q1A_-20^4W`-|(18KQykW}Dn&B;>$^`gVCNefALTGniDx zRnb+;9 zYikzMcp?Q44UwJM7Taa!)}a$Y0jx;F<{R&=@pX>mBwD86$3}Cfpux@ZQ6d4TO&kZFsk5Gz2q*V8}JMy9LP%~K)l}QWiL10mhCUwZ7ua&!(yzS zyW(xh&I`c42(jfylqNre%k}}0#<|(?M#!1abl$t3q7SQgpNz1X=W65_7aES+I$Oz) znn{>AobCg~WlOxO(E4DkpUn5RO_{(8!Wo{7OPsgR>7)y*Efy~eaS30LsN6yM+^`&M zHb|sUgg<;&#Y}+G9!=w@{+P*XKL4c`;38EV7U}7S@k1<1&CSU4w?V1Hf z8Y!OT2Ur2XvMZ7mwNLh?wrQ`Yrjfaz%tUao$Qb}k2&oeV$N2H0xi)^h3QYuOyPET_ zB)_)lC-Bw-j0mg6CvKzI6ln;{$+pO9gBv7jqoQDp|kA5?t!pL{C6=e zOjQ|V2~Ia?!xcw8+C?t zH~>HZrG1{GeG!?FS?9cE=%Sgjy+33ms|y$;byznq0t3Nkf`SIPPik-xpAX%Zg%Hj6 zylafmn&}iv8}jB;r*{8otuP-uu(s+=OW!Ts(;XV>bZ}OFEKo^D;XN@-;}D+SzW4J| zWtr#M*mBPUJv!gB4BzM2uc~<)9*gFv63LnQ&Css>-i&K3HS>#f#C<1 z6Y2o7Ro?eJd!VZW>q1Y-TOChM`VTWXAX##ch!GeY<_an7AEi(utPsp(l+gP3&9g!S ziYoyowBgKEQJ}SdV^so5d}E*7E_FQ*Nbmra_D664Jv@0CO;jxapuZOd*AV2Vn=7AJ<0ZD2@Xpbxe zJea}R2vlMQ1~)+U{w8n0SEu6fY`{hMYk_v!_6|vUlrS(VrJ2Fx$i~kKiccS7PIq5_ zR*GTKEtdj|nBgmpzk9Uurf|9GdR^!*20prHaWv-dT}+`S*pbmNc_2)i#03=^LHO&26Q=Z_f|IR9yhEsQGlc5m_o?A^GtU zsx&BafG=JtV)t;p^>>cL;V)=E=a2}=bkJp*!U&!0X12)J1pf2dJ~!_1&gzVQ{>O|~ zPI_UBthZ`%>AqXtAffpd(DvmMHUV4ax*r;=&%{;QG%wZR(Ff08iL~Kxk(^7Mv{mNQ z#F)z4P8VQ4eM}>5Doe|7wtTK=UwQ$2?G>^R^gV5jh&O zzM44&{9eu)7L@*~Qh4Sv%~53?JN>}7V%zaA--Xj|11udBouKhoB<|xfdme>3G~6%) zbW{wi!2yeAZ^~OsBK#{&pDcu>%jd#z!+o|9{cid%j+% zD?!D~g_h_h(GBYC^X)clvE$wA@Fh_>sLKaCK#NoZ1rog*>)m4Ih3&y2IiXf!v@uN> zhxe_=B1zeZa)LQGc!Pm@JXW_J_88E$wdE%%F%Iq3OgSzVkYY4rL6LdDYO!TRrhu=f|+`LV)~yJA?^Ur#1PohAx>YSsWRGDto|(cjxolUVdPY6w>L9kdiWz09l0AiLb?e;2M7MQ9_kU| zU$-e)qd5DSdTGIik`*EQeqmwOCZ!f&d>ySH1hT<8fGz#%(5w%|Q5^teiZ*#CH;Nmz z0*3oM(cyoE-SDz$R*IX^Vg?4ViG6J%p;8t6U6TNH3UrE!(u@hGLxT7)4;y^6z10irA`%-3FJkY8nz4$Sr z7PO;oPYUTAn2UxAw8yRaY~*81!TcqQa|fp&ayxxLn);SG@jHUs+@tk+*g0KdssfTb z);@IZvh41(%diwpl|ONbclk2*fFJu9lJ>lhiS0`lfJ2|Mc1T!CGxO0&}$~oY@0hy^-wl|LVJ(N=s z8%y-_`2(Yj=Nxzdc+{v%9-SM?iN2s17^EggFfX0(1#m6gLF=t9mEs1uAWsu?bPTLp zyCVcBxf)zrdi)PI#hyL}^`~fhK`g`W(Herb(-kL2<3GTHq?$9%)o&7x+*u>&0DqO1 zJTRC<%zH}r(0Rn)$<-Kdb^&oA8cye%sNsUotLtC8W%tK%-;pW7PcrJl|@V?n0gDcNTYVI<4p7fhGf9uVrv1+^G z|BMUz2Fx?8%6`ujv-bMs6{ejcasO4Z<4PM=6*TFc20y=I!M1MVh(}?G@h-!xnVLP* z=$JBGO0YQRKJAUTri?5$LTh|npcwM zOeiWZ_C=C*ZztVjUU?S|R4QGV7iP+++g;<)13OJp?>#i}P5yku*au&KbZ(V{3`7Znm)Kg@y>WKFu|b2J@}rbzJM0L2WfCf{^# ze_(fw6LD7ANvFkQNXVohK=B7*^mIprL1(P%zo6>>Y9Pnzf4gY|Y&>eY^??CAgpS7o znCf;{ecNqLM>=5P`^2awj^Em87w>MwW36z&3(9A8)*~zRPx_xLX$ApLhZ&0yiBe1A z8w`!B8l?3vyB0DGF=5-;Hpgv2ZNB|=?!$j-BUR21m*X7NG4khb7CU2911ev=)BM*> zsrU(nmK~$vG6r!GlnGlRgsd&;n#1S-KzRI?`(ASMp#GWB6%CmjtnM{^Da!Xup0qHF z2A4Kw5XQ|_2aI|(1TLJIP{OV9w^$Gn)9U!N(H&3Zv{l|Q8(&VmV>H^r>KF^Fd7HNV zT{0wUysK>9{@0V*06t!uSNCs^J;0jiJR#x|{Sc|iAu$VbJ4XH#(lUP-jF(?3eR2-y zUeDMxU5Q_B;m%mEU(!!E^~9*HsYg`8klGv{q$t?O9xlnK681|NX7u&WYa3?HbYw@+ z-HVH;$PWhL0}?fsb*;t(T^-0`8zRm(kX5TKLjIZ&(5e%&hIs~u%VRS8 z)vtf6UcXki0OJGfH=M_zl&${^6SE$Sqg)a+eHfj9rIfwr8F zxTS{?Zhm?8@+``Ow7$&U;~;8U9i0+Wg3(B9v*##vs@d%Dqb}B+Nt#Lw`qI{hu?g1LrgZNkn&24`cnye!EO- zUJ0OQmH^tKMW6F^rl9lQa?XA({ASMp;|cdXWzQCl*70hyoFg#3t6Y^s>hZb=)u4=?QI_ ztuKv-9SNFPyI_X4tl6ar*6fevn?H-jE_zE4fD(GCK<0=YP^tuXcrq?eG9jK1!RhQt zBk^Kf2tfqQDEWCVGZ+(FsvX6e{C=rXEJzlI+4#1qfL6ARM1W?VwY@cD#`j~iF! zlrWo4R9p~`i#`L?eN68Yggmf7#sF2MKhFqkg1&gYsvJD-Zk8$=A!tMD=w=R)5485%3?}rCd)bz57RlBC(s{o3*wOR9!59-V3w4fpt+qkUU8KAg z<_*B`II9wFwD&iMxCMWb%hlv=qM#!hhjOg12_uU*aEv7k88Na;FH(Q1taS;}M4_vh z&&7THDnwWAgtWrI@m|<=R}>IZX<+hJXx-6r1j2%0KIy+5cI|B}jk?+tR4uzYAdA7i zk01&MeI(JNMi`vheba%(`hne6eK+A1S&_hTN;foaio?1vt&lX)BDn>BT$*y$?}M%4 z@P#033_yQbZ|H@(Ga^jb*}542Zln{Hyot!eAq=EQba3uV;z+GAL!iL5fcwp}nW{GV zl+@uAwL&B?2Lti{EtZa&-4pSPAsy`yFPMpCZ}@p-%S<+l^|qp+t3vf6-0usPNVEtBtJ`3YyPH92<&ptWLKnyksh~^e29&Jf z-y-yAKD9GsO08szxbEu-&w8?y#{kvOcsOL~`jBaM3D)4plZ@=DQuatoHya(qPHlt? zfqk-y7@>zQYc#jk2TwaUC3127CuMT7XSjM;vxZh9E5eQeZk7kD!9)-1I>V7hC)3@8DJDlDU-scHEVf{(J>hh@L(pr++1x{0Cx?!P4gx<88Cg>cnkkeYA?%q!!Bx^Nh5N1Y)QYe z?V^MtC^z=Mp|^f`k1MHgLRQwp;dyY&#-jNNv|0=ri>$4fPy_L+0*!8ZbfT>hg?Ukv zWN*Dm#>=+XYuab!ip##$Vu7j3T%05uk@A1=7yMjOAhFA{I01M6MtO9kFgYmN;@mr} zOm8WtY;J^(v76gjW_=MfV53W%Sv1t21nu+V$lsKGErQcKK*jf@VVNE_E)HUKQOR)m zwxuHm*FQ`8gH!~frN{9Wl!eAx#p7AC%-&Ax(ZQ*-!^KIlC^D-9i3*qGm+ZLXvTyr! zWjw!u>C?mxOfiKA`P&8FG{&>_Eo+s9!AVS=T2}gNonb_af$JK)$)hXW_88%yq!T03 zQ#DH)Uam2n#L?oLc^a8Cv2W5IP2;Htmm8?6m$^SoWMeDE?78T+E-hq>5%E8!lc6I) zUMl)!6&@SNCt|gDTv*`6sHIh!ft}IOhalLp7-X@QO}Kht*#2n7!ptKzFUy?I$$3qi z+45273=OL8yvJx}-I&zyXM4goqI8jGjmLqtdnWg%#zr5^F7uq7jXErPUwi_jB*siT zNq}Q>XnYeRDkepA0aY8^4+vi>i>RP4&~5Rm%tA5td*$K;=h(?`6f;jw8w-Sk6^Fqe zZk_4gt|d*H)9`XggS{Um;Z~g$@?#0-)WX^zx^(fzab#!i^BZr<>(Cn*9gEWMBMdl- zuY-^;Sk&0iX<^XHYzlyV>ju7Kc_*LVsR*d&^_q}bzT+PR6r^X-mmKADg{C&=2Kg^o zhpPW$TZnd6_Ji&qV`iFNYwiU zwdnMq7|~?P$oJc7luHemr%&kv-lApTffjsM@(qB_Hn~CP6#9B-_Hq}CQmOjG3QacH zI2;^Z;n@oN`m=Rt4W>G!UendmQJ%P@9ssSIr+cd6;9(s_w1&sX*T!tVkG%P`5v&2% zWN2z2tY&Q*WivC4A_!y8zt(TA2|j4N`CeLYqEx@>@Q3u9!Xa%d*^xpegg!lXS3p3p zH}reAmanT98;KmIWu5kqETRUZcU_d9h6Jp5Gm+oF(|bgOl6a^3tT;M>N#D{hq--{j z5FY<>@~ zq*_5pI}0NOl(-xh{6TJCA{XZN9Ife!r#aXs0Fa%IL>J-X-?uk6W$j5cXXmW=667gB zF{#v7_dsBOvZ4$b4Bost)|ntO&r*pbqLho+CfBzN7}>~Y&A_sEl<97L2uSGI$O(!n zXa_nWC1qQ0=c?GPEZbk(pm~=bDT%&Mckd)$ZAH5Y0oJOyy?5^x;1aY5)bV}`wp};r z^@V`Kq3~w-rS2A~T=gL<8lV4lJ#yKZZBWN(is1RN*J+bOLDjxuZA)w7d}yQI9yXQ; z8A`qqX8GmTq;;8>c|57n*SO1M)DmZ8wljc&8}pBWqMghamit)ZWUUXHk2!Q!6zUT0 zGA}7<2_%HErf(iz>z1m<$9l%;3CUGVWs!4NYd>C2O zM6Pr|_t_w-2Uw4F(u$myIyFikGsq1un0UD`rl;7q@t3<-i5UM_(TO z&V4ivYBQeSBUEkh5cx?`@q=KIp|i0klo$mNUFSlr{7RRg{3j{f(5!F)D~GL zNgHNU&ou~F`52BXY<9Ycvu;V5^987%(3i?N?+}k)FafJD{xWtHMcL`drbjyFHgHtmM@Bst?e&C0LxA9=sQI# z@LyIhv;{ZdnpQD%DJhh-NJDcxreVDD%<7)Rlg#1e4fgJLAc&ZM(b;&j$0%%qTVOs$ zZdW8V4_66r-FZ&krGJx>WLa=e?mQf}G5l$5-U+ht6~9P1`0z+CG7DqkNLg1RJ}6a? z&)NEyH$>clkpM&%z)Z=t7NeE!IP(7h z@FiJ=R=6AKWpx5I;Fx2R>2}cH(>|x{ox}TnB4hYWo7uu9gKwm(IPT(99Nu{W%`sN4 z_u!W4_scuYeOZJJxUfM1cgk35H9+*lqS_lj&VU_$>8c5@*hxjjbz6X}|Rc%_zdC9eoQ2VNK&HTZ?|9|kl*&%}~ z&q-=XSI->5BMGHL!rkM)QJJzf%;QZnBvsg@X6<1X2v||YeVgTe$vBrhL349X&nMci zX&Xe$Pwdqf8EQMBUH^VBiTQjh36neg?}jtJj_V;vHUp+y28VfGUN|tYG}M1; z;7KI^WRfQ?u(d?_(E~AS#|GbVp#X^QfW}UP0lPX~g_oz4z_Kj(r=XW<%cC1}Jo??l z<#+T05VJVnutE&GfDq19#m5OM1Z`J z@v1&KZp=7lixl$M##h4mj*7cDy8^LGnW>_p@+b(*Q(F@gF@NFZzaI7i6rGU=ZHx5GO9}DZtr;&WKe?dr$wIU>Zs;fRQ7xhUchKWA>0;_~O+%O->MM zQyqP#TT`3!;&tKrwX5}OH|o~^YSqj?R-XQ?Zv9%J`n4|y>eG+atG}yI|0`2K;OU7h zaI)f#7dD=0UV*+etB>Hh(tG9=cBPIzh0T6|EvCa+$W5k@xlvi*M{zNl{pP?hTmpqA z#mgVOIumEHA8V9X&b&WyDVRAr8^c+ZWhfXIsh`%rC~{!|TTHbY)b&FLLs{E{ccRNs0p zSj9S@!+-?TJtR{XFS+YPj-_vpa`9=uP6jsIGigiIh@=qktA}? zMNlty`wbmIHQT_=f{n*3P3Lqp!nkxnkuU1m7yz{Kx!*likHRlG)iKu`6cC{+X2*P*R#W36S3tT(lSMXTWzug)0_qF4x92&zsHr|k z5U|{kL`;~r;Q(Yml zOJ7mD7Kqc(&<~l?=Z=Ywa~>@PiU-9Nd?QF&PV>KqL@cm_?u6QgD9Am59AGZioi#Ty zZRr^8>U?h*?p8$qWb>|&Qh+^?ztLzoyqhv>mO4o?Fst4%(4Wfr_>lcYZ&z&6!S=JS z5cohcBb`2Jo|=lwDa}nB_G#L4CTH_^%bQWt*^k}f4Qn^(HYE`EFK94U`vJn8&n{?X$pw;XXx9+#2LN`j1N)Hk?4x4c*!Rm_=2iR zZp6>JAakFJktmbQOZ^MiNy6yt3lgS0`i|P6`1=yhsJjXDElIneyE}n+E-Z{>CN%+_ z=0~hC0g8UAM>j8v7&UKaN+Kl($41uGlvS#MmyCW0T5FEr!~auv4e8n!BhLN$n`#+# z84R0kvtW~{`d}<-J>eKJDkvLZ zf)3JC2pq^Dtm(h@qDq_t;_qv3J&o$5W#zoxQ;aB4*D&a|ZQHhO+qQYywr$(CZQHhe z8mHZVzj?o8GXKn6%v?+*by3N_soIsDwX@e+&lfWC!^mi;jI>2GQnh@<9s^KGRLJY{ z_z%7P6_3mDU7M{ed!@WPbo{%y>`eOMYfc)b$V66!U~C@A|(WJAR4+V1T@ z&JtN3h?=fpPnr>*!R^;2hD%eq`~vFQ4g%L6#p+Nl5!+!)Q)Q)-=l!Ck<-PB3kMl6^ zO|diiq*U5|m|zz5l#lHioustFBqh-N9HV4eKYok2yR*ES2^tZYsQSXB)VG<9j)0v+ z@O7MwBe*7Q$i}G>&L9V~I6C8RiLrq@q2rk8h_*LH&8?W{HT>-GOFItMYZ5)IE^&j# zCd{oM_N;!Re{Q;#a99leG(UAqX?n@IocI?esI(m6oS0$ufr9e^iJ%uLjLrH{i@PEieb}%$CSGru7${C8!FrzQ}$?Aiq|fW8Q^!_NiVl>$=8@_%_eVG zecJTUZd(~2UYHBFLAZHgZs<)Z8w&IhXJfTvA{_oem}DNb$iTRd(CqSb#NK(k@9HFJ zIc9wb?cndlD6?p<(uqy4{=Fo4$+%F5k+0g!xL_tAd8Qj%CA!+VE6NTY0wG^e_VKCP z)*?S=O^vl&Eqq!IvzTX_O+o8A(%bA(F_|H$`M1J}aq-f>vmOKDf>9|n5}l=eeqDFK zm_X=@0MnneX8?;#S>Y#93tfOhN>|X}MxsQ4y}ORcPumwP&)7e(DJqiM(>J_Qk<0wS zp+b2^J=jh(42q>dmuY=2HJ<0t=x5kRx*aYx^b?HX%0~%i(hY%#2ig~_P{Bv1rSt-B zwD>`xgI+NW2iC6$m4V8Vx@LN>+6dCTMzx@r*1lUpEm^Ghp!B;uQ zlwlYGvLU9H{iqL^+6#CY_>X37ACfb4P$u5f;*(`5U2QEC0f?9`M+7H!04dMG<-U}7 zdkdh&)UE8ag`1N0no8~xA|YkeE^rX(DbYIQnW^n$6N;}BigU{sfRIp8W2y&gX0O?K zI60NMTml40Tk&tkDUzkSbkot|`i2|bLWfvmO|n>ed=~YM`k5J?t13fs)J4TJ|DIB9 zS6<1~wY;}cIRyN88;y{*6)%)|s#wIjxnl5i^*r;}q8*usO#2gQacbhkeX9ZlRQ zW!}mUs0m9+&m8V51;3Kw5Q!|pqUu^@52wsdKynOW1XZ)>vh^R;#X%J1PC+8;yBdAG zDGzCl1343OGL^;(9Rm1C-LZ015YEps%6cfh_rHx*U2(Ds7gG!C^b=*2fTH}D#KYl3 z8VtwpE#H)1m@fHS!~oNBJApWz!>!`s-=8U7DZRGiS#iRa1?JXFRDCsvQanO3rPt+8 zA^R&Wr4`6T?SZ$J+PwR6MF=;#MB!QskIGI4;WvF*y7(ENzw-psD7V9(>p5?!XUl44 zCX`8GU!a@v{daoymcNFZBiQ4XD3dC_zd*r7isaoREwOuB#2*iZwpC(k9g?;e8G2&t zANrmHCgE(WMj+%CnPo1@ZcS)^X?ro3o9tT2*sxAZO~St6!;H0RAb_5`{o2hQ=!_j9 zZtWacP!PXmM&A?3kvVCX=N4D@vx`!{iiP5Td{2OJ1GgC;Rkxftt%<>^s0TD37!u`zJlY=7c*@42O7??&@gMYVK3Nrz8)0gy&u) z_S1tq1bPWw<0H~rL_1VgoMU4S>0>Dfdtwc^>l(CgeBRwoz>tqFr9{+octbE*?~6e0 z&vPc!yhm0Eq3UFO7m4P%KGSzKT8IA(*}B)2D>%ib=gn(wu;?5$3to;-rj1iJcRN>= z9^%q+UUorcW8}mV3!X&M=H#GAxiZ2b9vWD^!4@_t1TH5+W}pVEp|H6QhE+==gnxM3 z529xKB;^@x;SX+I9H8Ed?UGLsH%)kj&EK*jJYoq?!B7wFUfJm|nk+Vjy=TF7b#Wbo zzs>WmuOK7**Zq^x^`(-US3T)}wBHuL_N07Jq2U&t)_d33awhxnen7WJX-$WU{xxOJ zI|TL;qetgS^?Y1ZNv&-aT|J)XT!H3Y^#A4u+BR{Mmj|XTo)d2Q_VZ-`{mzY7aQZkH zHQ$z@=jJ=zGy78A?a}CZkx%Sh-|kkmTfTfXtLf{uUl&8T2m+r}@Q*^EOHopXfEpoJ zYp^vfcoyUzON=G$F--O)Xqdo5yE6JFMZk8zPtvj{9C)P&54&sv<*Nx?TX3)hN<%0q zXl-aw5Of~Cwyd2eOY4%)BOxh}OGzBju$ziZ&}SPaoQ#1G`dIr4ps%}9)1%p*_o z^P)_v)1uAMbxC-QCIX9Y;0_SDt%M~>*LDs!OCZwZo4+Grkfsnlhp}uzt-9^t=1n7vZ3LYo_yvQ0&O^#l0(RmW@m~q^ui($s0$9)L_uJ(D=!?&tIaRrdD|PM z!ohW9PsvQVYSb|)F(*8Zx`v4gzx`ohxwcuKcbPQbv?$?**YQ4QcR*(S2CuVn+B;Vk z&^*{39t)jFA=%$mt`n$Y^5Mqg5pcJy5p0MA(cnHSws+S_)V4VhHF4H5V49Ds80YW7 zm-&fld%yc|$eG}RU10x^>O8;JtENcUO zD_y=CHBF9wzG^JyyTN~08ooiT@}~4Imo&eFZ5e?h)kyJW9Rd;*g-=`&2maB)roeD7 zJYD2_E`P8ZWn#Fjm1WgwpJ{PwbCQz?4{vdAw>CRnVp`&P!pbS0^XR*0JiO;rp(eaC z)Wpq}XeYIoE~4_xcO+xDphotpj`eKvP@Yll&;HR0-w_!lg-{`vX@e|eM)cgnV~`Jy zevJD~*)Jk|x~{R0leuoBWYv)M$th<_3=~0)^A@-Gfue}@X(JG9N{B$p%ScV%a_<{` z4iM8#wz^Y%aFzCwhjI0KysFZzwDVC5x~FDA)*X6_eIwgZbG|kk4Y4_usx1hYlcS+0 zMjY;$aRj@XQhY&@aCZGoRI+gr1`NG2Se!D3C9U3tZ_L#K4C?9)g=D&+K_XmzF+b1@ zb3=OFS51BNKBSjNeXfXS3Xayd4^oy4J9UU{>rpU>~&_2I^f+Ywi7UH z+GW3F%HL|%`SJumUrfW`ng!mOIAzWEEPo{`v?=@|Wb$;WHqxch=$dp@AfemG2IL6( zHzy<>D-_DU3Uw4xcoRm2+%<6thBo4eaYxm_<-p+!-vf1r&QBq6qcJtW3_YNVZA8ji=Ced_sdf&TNA(*m zvU>ILTp>h?6QxA9FL-MQdxmGIe6@2O1+!UWt{$D~r|3Q6z@BbU<=iu%C4E_Ai$lvk*z5ci7|F6)`LF)fs(2vh3g&X27 z1xtP1foOqFPzdKbQ!q*ojZ!}B==TILNiLgxNpQ-kOHOg{;0zfFFcmU3v{(2s32|}; z)b1_nI6^Q}?aY&={eJAgpXhK9#d^3W6yzmc`$0*`c|hJvA*uulvKg2m1xsNh5aJjp zOXboDwh~PtF2{Ewya7p7&p>!h==zRHjO)}7Q?Cvm41TE%mrRDDMJh-G#g_U6ht(Ol z_+b|{3X6T)QaZlW>i*r&ZM~TWvIOr`40)8gRK6x$72O{itI&Q*GM9v)!k!d0`P;I% z#ImOJ4KOJx1L-1NE@Az>|LrX!O=xY^+L}UKDgf2E%r71q=C+nSi4jJbB>tYQlhHC~ zhPN22x(cnjTl<9qvg>e`VJeXXc6Ge7f_jiu`3v{xGtNrQUdkO zSLWZ-W;$FvW~Wlgfgs-lH}l~nt$$eEg6;Y}9xha)IMXseq5B69;TzgUaW=$~!WMdf z1T>+ezaTHBZSsU96SCU1S2PvLmk|FQvbEX3m09XumT008->N^l(bpQE-Co@{N$gUa zvUC;D;FDzvS$-}>BUaHVs`9EzLi~dYD!%6v|KGVBTp#a~ZD)E2F@0*BNkI|HHg`uh zXiML4>VyKMhymWh_t8C|e^HpuY)VFZ>_DtusEwW`Hz!Fik1^O!MS``>)>xHc(s(KC zbF0@%Aa*u<6QylhpI$><tRo+AL(eKy_#=0y7M2>qeMD=Q@nnKhaP^r8RAc|R;WtbMldM~)m$FP#0tEF}Nt z$-IweYr8ZmV__kP5=a-iGz!R`;7raV4bSI169es-g$Bu#UQV~^Q-rO!BJN^esAK5?kQog`)T$dHngtQdefCAgU~_321QgKBHbEu4#LyfIVUqR+ zx`){>+-WCr72Ff7R+Sb!exhN9Z&z-VxSxyvnX}Qy!1zPFj3pfSo z$J+dU{hhhqj9-6;m_bU+Am&YFF&r=8{sGZ%&2)dyqI#f?=+k|=vf};NRt)koNrlpl z@Y6ShrpaaR3Rf*x9;MgpKngM?A1W0;^m#g8z}uqIG^$h5o%`G|5H`_VJ7ilC9gjtZ zhM2=8Q$FxAl*#wStz$%x)@=MHw684uNg=FIO2W%c^@)QW%Wq^Z*7?$>oWW(Xflt$8~MwVa0s8E!ooS4 zeK_D%?^u8_?L8`j%!t|Fzs~sj)iO_wKLlMroIzyhmQ{cn4)?{w12`C4O~DA1`?fJQ ze|RgXWwxHhTD;(3s}lVFXQus_D&CL!;5g))fmH;QYE@a}WrZ`;iVOVTQ}G+E)A??_ z2;dwnx168W4Bff!`U}U`wWIEi)Gdg=^=4-9&RDDxMOA7+M)H~Awa01O^_69>wjL6%N`F)M_b{qy;X?Txj&$<4@p$7eK}J;}QX3&_DpH zcsLZtt?}(}Z`KpoESvrvunyxFWA--|JX&-nh`3tpZ{E+iShMX`o{}Rrave}B?lXR zPSI08kY8+gM^@wC#;DxT)yAyp*r!@6cdX{mk$ZFxP-6^po}RfJO^HGRA^@yLQG*+3tN2X z-bVD}*y3pOC>pZcWOs%|W$sKKZmaw{rsyfjUFE!G1yARnt{F%raxLtF%2cDi3-sv~ z{T{Sy3@S@_wrR;zhhHRB!ZfQu^a%kl|DwVsYBC95;GYqK+n3hKP6jYg-7&N2ld~Nv zrQ=u}PxznM3znA>ciE(Yhndhvb_k=Lck>3>)-3w(A&|Yh)#(mU*y)oS+JPww6O`o! zXKBkRiW6fIs6-6&*f{%vj|)To!QU0pZK~Ka11vK7&29DwPn3F!u+6K<2Rv(HZ z8#A;g*i>Nesk;>bj1!#cDvcRmVMo}D@$gw`)bHEkK=M?(%6gOvw`!hJ-UGYzZ}0P8 zy4@9Jb9Dw(Du0^5C~ThuK^=(k$p~S#L)CiU?z8f31!9WGdCE3*&!XJ%3?ihycS{=s z=#C!QRROE1L_^RR=Fa(=`Kp`E^a2+VAqC?!^LXBqTvG$1#ab{_J}~z{$P#i+zA_(~%PO~9jwt(^P%|X?rrtN|FJ=E{N6pzC&{kKs^ z_#mi9_n|bVl=So%%hY4ZNPXHAW9|(!BK|NElD3j~7Abg)?+u+mm;OHeV3G0XP%~^^ z_#fv}Kv2AFpF69+TS@Y@oS`|BZfN@Z`axPL3{^e)hUv>2?-?R;cYf4heWW0#yG*+} zX^d^^i0Lk$E7E_EmKA5D*RZLxd@~237)~JSLBaMlIiwK=y$LY*dBke{GFFSyW*kY3 zm0jwDvYDXPWaF0;02Yv>#$i|W6_aK%%e<+&nR(3@an7RI{ zm|0^Jbmkxiu+eTx2C@CcsGsrh1i`$|qX}1r!-31>a#sE|+FUx`!hP#3A+W>=xArm+ z-h{jdMf#X;&n4xEhIn{99>#|IjMVEwy|5P-g9E<-H4qO#PERXb#G#_a?bMOy8mlG z?XGvIzpeKTtZ@itn7}dU^keO{6n_J(kT`;q$+G=5=GA$jGl{6It4?I@{M#EmUbx@; z9fN24(AfpJ0=L|Bc2EnYQVK6;F{Uatfp4L8@l^wej)@0l~9T$xbeX4Qx;s@$v!a)bbJnM zdFk|ObFK1n^;Q@v<(xsh$&(;tWXD83@Zxx#8@RXN9)g23Uj*h+#ug{EiR~ZI`BN^NeDrHEx=RxWyKhiWkq~i^kGA8ecj3P zl!t;xub^BXVtM8y);6N%I|mx+5p%b7nSK0x`}PLn*)Z+!SP#A|&Rk(Q-9fcHvS25_ z!pU}KCG0t?mHR%hT}dx8)aSR-4o7Y*=-p3@Rbh9`^1rzJ)l@RYU9 zTJ^CV2k_;9eb<h@rHBs`xy!50^0Z? zDN4C7=>6!Y>aIq#7EvO508{?BG^it7iOHqk`Vb{`+`%b$AUb#xXxjL6uIfEp7?mS% z%6@^kb3j`gNW7kyx8$gRJL@!W%nL3EcB<&9itlT$@8f;GVrk+6>_WVu6JbL?i}jV9 zQP;LN!}~9pcz(u7NU8SWJR$c8e$(Q(@IqtD`GcPMC=|A@QqrfzVa zTpw1*5zOHw(uM`H=)jH8JVEI&+DUG~5X%ZZ;qE3h<8b6)zRAI2S;{ZF4 z!VT%RQlF!+pzyyF@gE3w=cZHHsc(SX$Cy3qYhaA5dmpNYaVFNXq{_G1bJiiVG*yns z5Dpb$8gh%ZIoxcylSk1P%>0lXv$Pt4DZg5Yh?K2u@t81bI*Lg`79(y-5=29W=W?>x zK`uA|i_KDJAwHjqFmbG6Mtu862g}=zZB#$}hvk_uN>&cecBoq@4E4k9^SC$i=CVor z_@3jG(23GaFvobgp&*7T3bF1jFzh99CW|@FVR)M51G>si+Wo^P&sMIxQ#>*PXd*jT z3P!?AxekzY4?OI&eSlw>{t_ibA7JlDTmP92->`9PPX+I5PrM%)F+?DgQYY zV}-1&O)VYdn_3EeXNh)zYAI&0I2Dul6wnH1R}x%i3EtbkBhei?ATv-KFH?ws=*9CxfsBjK=$y15=Pq&}~iz+Dg#qj;#J7wFbN(|z} z(mWwgbp+t=3>3s<0l$<#eQW|wU3ShAGII!_BAG(~`qvfd83UDP*Db)O3%R%Xt9K45 z$AC=_Q-K5v@kv-Tux4Co>d8~+Cy(|hAjK}i>;?y6a!c~QviJcG*$=kjN;=W_b6j3a zvkQCK&YT{XkzIPy=pXak!eBLtVx%Nv8&MuFT&^`iVXZ(R{HE`8K}s7VtoArB96zwK z-N!v7-Fef{tWPxymjT=Sm>X3{u3v>q*|VhSuE`^^5&#kuvtGpo0Eo;myyko;oHHc` z1xNgVTOkjT!odpQRRwxAgsRT+FjAZi8O63bck1(aMymI4a#)yG9?8pCPt6PU^HT#W zDfO{5It=;vWBc=&=_$FaQegc8PUB_|houitt+T~uf4$5aaYt#*vcdPFxlbKHOUSr2 z1$2Y}Y+SUPVGP*rnP^Mfh2PWoXMu)kQ?GCDHaElAQ1otlcuA` zkjMVsB!U{b+|kUI$1&7z??*Q}awsks889P)*|lo=qd)>n46wcF1v|FT!E2BKx1vV) z6T*~GN4F_2JJHLKY+d@g9xtJlf(qtjnkMXt*>(Xw4TDMc=&QvU|4? z24Buuo=92)oeR*~T5d!d={K)B9-?w;;4Q9n+ARURn;Fr}#6e_5yV)xG!Hc^lfg z9%(_q9eAsV%UxAeJV^I_D$S&v#_SakNrMqrnKq7xo;*I!%0GfN+{3+;x~LnB7oYa; zSu%Q#TOBL%KaFrxKQtX86Ds6YYyL{05~`w)uS@@E4Gws~JZ5t-u+bJoa64m1UX=#^ z-l!K1ArJo?gSDk&9WP5~Hd@^Xm zX!Y)DO9XEf=4yY-a$3<_<<;xDR`_he1h0fzV7KvioEKF1*XP+{`Q%oO8)_BkNG<{) zh};FU5M3zi7cWJMh61B>fvCklL_90I^-&|%blDUvITa83Jx&xIllC} zGGVav=!Y_2yO|awNAPis_n=fKV=RFj&h18lK7&Va!T4AD*`crQ`#44(aB}sv)_oX@ z49)go?F(YLS+;tgHg?trJFz;p%EXTr9=01g`!8zW-9f zOa!kXVe}Ha6M^iEG{DA+0tSYA6G_-cY!yweIgx(fma%1L)FhmD>(}~v3^6n$1VGq= zXkk@tH7>Xba;UQoLx6q%@k`m8u~FTMP+Z@wAXb3X2B6n$N73`h%vBA$fRe>FLl)Xk ze6~RdJpK!(>WKwfXy$<(l5=3;8BrE8E~BN(@@s^#k)mPSR;uS$$OEc^`_JBZNTd;P zeLVnWYFex${)t*c7547tIfxY(k}02c{*lma(%`yFjd#=dn?f{UExUcC*@q%o3uKX( z!2j9lV|RMNcb+Kw2a+#7!GZ9-MTkKNigH^!zI|a%eBZSzWmM=^OF`=;VQxu4* zX@Ra+gu+fve#>5G#g9|dfvRT~H{$hWub)LCE>OC(L;(Bn5BT+Bszu;i`WQqf5}4>U z0GCKQq~e_&&vquJ^v`K=6x||iopkEiv+=7(FQbF>4jDFP z3PK20;Uo}t-JBOsxD;Oae!5d1h&NW0-3WmE0sA*BRMx(I^br)$pPZzUSE!esg>j-$VT@iH15m?>SX{WSH@g-+AV~&bD0e7Tj{&VmiNV^}Pw}0I$T~ zEfS>_rfi5J?3)w@-1ee&&Pe-1^C?;MjPyD_Si8T*rdL&-R#f`leK{JJWJkcth+m@Uydt$DCqnE!4ETtd`nL^%9Y$yu63q*{p;u;Y00 zL$c^qG|0WHCErhDgeHxlY8P#*fdH4FktmFM6{^0gzLYqbvJPP-o#g#U;m?Jdc?;SiS@)JT>r1QXhv6LXD^3f9#2ce=sh#L6B!Q1hQr zeZkc|M!oW?$IK8PtyW0o&KwBFW;FMDoFT>V4mv%Bwxf}QE zCr84t1adH(Y#XF#vCxjen)aRGx1s{4p7;V9jSVNma8%B%UmU))!N?qxJK7Gylu29|bpoq9Tz}}zOs(SBrWh2b zEofj_rAn&Gxm0w!JzA@cwHJZxWW*hIqZJmfLXXBBf790_|LU5-_@T`y5Fo_N!A1qO z3HuK=5q-9Bs1Ng5&w;F?1=o~^M?Ew`c9vK=kIb!}ricHdHRO+@)DX%`K=GB?wH=Me(iaZp~vJawksv=_k^7eFfqp^$0}|@&@w)Xt`_2v6IJxpY8#EL#$>`o5dg1knkG@ zo{!*9S_#>N8mf?I#S`cB?N+E8e|C_-S)YndMc%ia-iO$*8-Y_hVlyMlvq>@%uw1a! z_Xx-QgFlKtPsATYa|I&}$IhhMHs`x)BT-cPji zOXz^Awgqwl9tZ9m<6HoGsO{!O&7X?h4sgIAH3A!ToDKaKFxo@pFQ2s1c>J+qI5B-&6P zVD_JwQ^`0_S|~2HHI|G{*9}1@8Do!1x&}1nEl(Zg=C!)7yOxVS2*6iBOVw$L0R)rs zXW4rt?nM+7<8E9JT;r!5DLRWLo90ug-Q+ryQnN2ZZdamZ@g{M(567UABlsOQG8F|< z{mt7Yyy$_?-J$$(T@pIp1I$NpPzZ2Q`>mH=uq^Ya7%bw~Z!{3?@wr|0WL+MVx3&f^ykTuMaeeSEs;~q?C-t zFqpv}_HjW`pk%;rm^lz8?v{LHkA&^Q^SyG=dPE^o_zhJaGyHu3)Vw*r3cMuHr^2*x z*;u`XT9%d_qhm$U9&cAf?N*I+Ta>sXJl{;%_TQULX`6_6v$FHaFk_F@nVcWAcNF8< z*a!S{c$K6&H#umy7g>iLA`#XmCRnVM#~Rk1E@YJ##ET9ThPz3(S5(>bU4W3&s2YpD zxTP#7tT`xDe?8Xrej#<{JQ4`VaPk3aGTLu7kcEI1He9MzXm;VS`WLb(+SBZ*yzvx$ zOF9V?PVK`+-_}a)0#n-=Vnolx)>+}bq-S7}&~f<=>ee4}VHV+(U&&GClbbDWsKw!b zB*$rflU#hS+jwQ07GAv!LMEWLUJw=J_fyU8=i`EMqlaJ#7M7{G(rV z%%DY54IStq@}$mHWYJRGQOIdZj_mRb;Xb*?JnbqJI@_V&kFsuW=fZ+ z>2;=TS9DCHhk@az&*RkMxF|FLsUdWQD10GZJ#W#>qJ8%=e7;Nf1ypX&s0vnl{cHyF z1MMS(Q;DCBO78jvTw)u zb*AC7ji23Tk@aKS(A`AVjF8*nd-j!qYXuj=y3dwoaH}FG2!P}A{7h3VJMk~jL~}YM zQ}C{DPFyqFgNEI-XB7ak)U4NI6#zG7AV*izb*4YQ9)yd$H1SLo}8b9 ziT7mF;_P?S1;X5DYKd1pIYxB>cIuBZ^eZy0@qd8u#0>UNWN zk-w)w7`vB~yVsz@tSE)NQs1Mv88nSgghjvUR*cN88=fKZ+D; z(H&jUetsF=Cee}@v5k5&#c=l}*%J&v8hVt4JAAbi=P@M~4ieYvTj>WmN0?Vo*AOE& z>N-I8a(&OciBm!0;fqN^c(uZ>Kuq9#5LO!q%aA5dvx?tk(s&KRm9430C-N@t%cBfJ z{3Cn(n*TIZy!i1ly!#s8G;=4iuCZRgrL|9~;o<2qk?rmk1{I<+^ODqtNU=^m3H(-@ z-yGyY{QndTVrGHOVKoi8ceWGM9+Tq-_wWJtD_|~_8mo9sTd_#+2whIifN`X8ss|ZL z?XK}UGaXZ58eeZN21790x}XeXDRZDhO)guLYe2H&tw1trm>PW*Z#Agp9o4=X z$ws%81TJH|6Bu6i`YX<`8JMLz+n4r<;&!?~G6kj$Ba$*ZZz8L;33)@w8jiiVlM>1P zQwc=7(kQ6pD{-noWIp7i!3Gl%Nj~^nBszZg4`z^W1tPZ}e=l?$p#2UZ+`zngve@R2 z(U}}HyvKYDPfFE2`nqD^AKB?K+%TU!%NVlUI3s^86GS}MSv9+@+xBvQxg@q5j) zVPrinfb#Fy{eCOzo!@y)ne6t0hlhoW%D(9n52-;-N@L1O_w1k)51_mNJu&t@`%l*(2a-E2(f*vhYEAFeanIEjcA@!cG&RdsZd&A# zQh!zr~_J?K~2NHI`odWLm{{V{~}BHagE8KkC~+(T(eGzQrX;82&tU|It?KFp0X$ zkd-Xqa6|7!qx~!E0iCds0~u4OtNk3TORe~x{J6N<%ztI}CvD{0Se5R@7946xA1eRU zylfKKRYT@5#_f_bdC3xegIz8Z!!1oAMo0nSBwHg}TcY>YR0*-r?fT0PmEMYb{wS!g z#a_IwsaptqsUf9Q@&<8zAWQj_b@VGXMX6=zDgltyf30<0%(h<6gDNTL1asoW=z*Wh z*{0nr8zT{(RzuYPtHEz^(uDz{U42=TA0s_qD8F(O<_7ojL2dgh5`5_=QQhWj9~j#i zT>#$L(dMXiSRhp=Gq0R$#M(g1b6%0ee@D7Ecb=IP=5d_dh#R*@)kmo9BgMfiP^+x8 zNEDAy#awjRk-Z%i+F2-?-z}+{rXH-GgtIJ8qrbie zn6n)GTdK7+gwj^(iXUYkUs&~fDsrHjy#7dU4USPNW-?BIOs*Zw`3e1f7SA+@VF}n8 zd%>>yHW;|-b(pVimeOPhIpi>jkH#%BoXSTmNy(9A4xie#f(;}+4!i$(=ZUIC&ENrW zVHJ_sS$VR|yRGV#!)>;Wn6WjK>_DC4wGB9BYd2QsDuwbX2nlsS?m+9=O5YpBo}p5lMO>D_7KRSi_{GU+klxb>`cd8&-y zECIKW6u!%bXp_ zrvPyDMtHF2R61CdT_egdbqyqi%FrUrs3K&0oP`8mIF) zm41_97y?2WS0M9=PxwSPf<0iOciS52KG+X7z(Er+=Lbq|_-vyV%iw$dxRF76A~VFz zz!aW%O+Qi=6{0QcoUH91>i9~sN;tV6Ta8S3^7wJcmCiZDv>NJ`JIo6Z(UA&fE4dr% z77|XF8t>uvvv)>?h~KM!JiB3F-fyc~WFTFDF}PUMXNXWWN{Ao`ys7zCI#C334FCh$~$1z5(AG;@n_2vda&hB;>=GUn!7tGo4*-ogf2m5r*dlWvRceL=(- z2IAEr`P~KF>21nax;n*M4{4BqFo?^j*h^5SH!~()vN3dxTJl^$ly^Gz_#rS4qiHJ4 z@Exbm-{|@-yYEdk%_-o$E^a!i7J)oqNH8C2;-wYRtGWSx_p*GttF!rJZAiPQD)pWJ zWIB;Yw04Jk@)2l^HU=94WM(Zn5r_@4z>Fi-AZ3r_rzja=-^yKkf&(8Bxps8(kHZwB6M zS^baIb0Jx5?&6+(%1fDZ@J?Qpk#`*^6$nL0tLJ@DsT~N8P;1J+P1jpePJH?&7sy3B;bHib`>$Jv#iK; zU*Cr4LE+8Tsv}@eWn?}X%*)E8d9hI?{h^=|I%WdQ`Byrb032yOYp&nWd?a=E@K{x1 zXq~EO$^P@u9~OxegCT0MR8N|jS}q8&w9%qRcigqL;5)MAFos%0Bnqf?-@^WV?HfGj z*MwcnqoD2vs4`GG%oC0(iV^q7E$T}1^U&gCPyZnMFqK=Gdid)$T|?}_x67pjeo)Es zhp6{ZwG<6+?elKsV8Z7%_3e8r`N2rVO2OVvJ1BY`0SVWeR962lA-?KADI zU;%Jxzt__%43hG1#D;6oTVh5oGj7F|W5_EQq9lIBn z1_3=IuM-h^vx^1zF01CH@6Rc01EGR`KX+%v9s_cbLc8HtCcB~7hp5K`Vc0s4hS;uea z;SGX%as{Dyi`yi)XpOYZ$j{dDRI=Q9m9?`^PX>U%E9;5@cdhmQ2N$DkQX}Q~lp#ib zK;anOgSY{Wk9Gv}6l9ej**UC_!}mbiA-{t~3Po*tB|`&Ega0dC{O-7>fo) zEeQDH2tdk4_4$urDJo)}KaAi^RVH_A&%Z7?25b8|_gL92YVsOek*=IWn#M5UJ`?cx zG9z9E^>;dw--tF=7>@csXrpk$_8_rs1ZrWmLY4Y=OPk`A)l}tkzhc=;H4%m#Em~w} zVk?W^{aYEg_{G3;cxG$$Le@3j)ZSsUMQ7LDtt~ihTK^h{!8_{`JI(WShu{Qre57LVM&N){@s6_3qM3;`}IKf5iJ^y#@?sp96xH8GNgrbJ<$S<7E8`5)Ki> z-Jw(Z&gGTXBu6d0zTN?cMKa?KLvYI=XCiICA(v-rS?=QfBJSkcw|E3y1BFO9zllPJ zeeDn^$4`Lgyi-zIrj$*9kDGsCcrjG)G*T28b zh~Qsz%0%;?`zCwOwM{IqD$o!{faX$P?CqUYjwf|%yHuLZ7yC{!XZ5eVqxcoB`@4sr z4NEn;aEhOMrugSt8-cWbo*H$m`ZZ<@JVhPPv85J&^zs*2)gL;}aaqXiN$xZVR@8&iH3)od%d- zYE4c}j1(6pyQvs^3y#_N&PBJiX^z%KP1IoP#Gdxqd!jwIvHQ+F=tKY>GbKL$m+`U@ zkS^bd*{;LqWrUc6nMYltduif}dcmL{={c!#Fa;tu``Rg97eD4f=bvb>wj{mmwpj*atpKXv7 zyVuen49myeOi3S5I)sF2kQY2L^m1`C(CDym<%qWwrov`Z2#y)(fBn-|kG6OFV`<`) z0@)%|R1)8#QAcLC1b_m7wPX8Z%vC2b;G5JlzW4t1NcR4>(|_g3(Sg(q?) z*X>GNPwxENm}KG)3=AQxv=gSSJ|@+l>MP`y@qD;mie&gof6j(ulz=z4Rftqi`L~Qg z{oyU{1lLqnS!MpjQ7EnjzxWS`1n0BBokLadhq$R#o-$3HraNQ%Xi1_;^y}?YVaTfE zhpV8x-Q1Vcn^60`LbTa2=LOr&c-j=OXGsHTRfrhm2V0BPZ|d`XX~mRH z#bR=>p|33c@rhAjqfNNLOD;@>Tb@?i#3SETqJE+44_Bsk#E&B-6>*;3WA9_3%FTpq zTl^S&Bl_01hiA*f)k?ws zpaFKX2Q`%GKb)~Q2nNqC%SPH%fxl|XoeR<_feqq9G^8Z$30XXvY`)f*%#7ebtShVZ zSMo$8;?ocV9VMvNY!OZ#JS>0lJ5$E@)v)*y)f$6lOiu;=wbPXpWil~zc^_IgCWY^| zm60pUx**>X3;wbIZ=ArM_;ec}1&xchHOSYbKJwd=fS|DPRTuhSOr3+4AW(a3+qP}n z#-`;Um zKnYnoQJ!20c5hi9I#ay~nKY9p8_Ef%T))&fZpZ#`1=@VA$0jI|bwJXrL=6-OW(0=CEdu)?c~Y_o;GYtgYkz-y zX@D)qOA&J%fl`-HwyW63xEh+t+k^Qc>H<@k4iBA3@x?rt7(!#NuHLUbCKq3gQ3I_T{43s zZRr)W$(7gIMDHsDx4Voz!=)ZM9L4TPQAERInuWBMsqZASskzq^dnsr*6ztHY`y=<_ ziKg@bS=J*fGAq0T*`*P!R|pK(2(%b94%}p+SaX54TB5{AA4|PORAD8vNH>xXUaLgT zAJbxmT+?alKjUJ(C6lTW$q`3H_~;MU4CY3RNu^W)u;%jJ12BjEl6c&uN$il-ZSQf96qu&1oWH(#{Y`{5A4mP5d?vzsLsD zfFBJ^{${ZMW^K5 zmDQ%I+&MPq7w1!A@Mi06$Ly3IK|B#+y@5@IhseJ?fep2ha$8sm6KJ+we-19wPbC|?0X2BKn$C2t$Y&A|&b)un5}?*5HcYg(vm8v4v*yMtHM_<~zof9XOa zt3tbuL11OYuP!21;@|iA#)Jm#S;0c%qgBLIMl&l>4b}ynuRy+z#5=8oYZ+5*IENV^ zZ;)#}(0a|}wWbfCqTR0VyyI-qbdC&XuU|t*&=aeUaq4+rzV|q$KYWs3!ubYGP##Ca zJc-%{PZd0_NDbu~?5f3qDcm~u%-WbfK;HF9)zw>jk7|Lb+OiEhK5VM#%yipxok1P* zY(f%LS9(alMH;0w>?cMv2X}5z3On2~3$dVB=HTKs5LG6<5Pq>^1y@%sEKgD|0x%Fo zfIv*jYm(E`m@OTx`Z@s!`eN{i=_KDc8_-!*aPCUC&X{mmUQdtN@(n>$$MBgfwqF2- zd6wE35IzQn^2nFs3Ss5JBXJ8L3VaywHjHE)XjYvF#kM`{@jyQCcP=jmXMYaH-WV?w zyd@e|bs)IReqEZE!kFF*+yZ!OPX!ypGw-c355op`UIFW?p^eQ-A@zvu ztI2?F=ij!DSr{uQ%q6` zM@DG;exljid5HTH(N)cJA?+Yzux@j<`dIfmd8=D$`(77VjeG7kW-IX#-$%lZPn3>F zlAe7ry*=b-mf&ua@K>#L#z^wpw_QW0pE0#zy)3U)vUwweMvH%Tez|W-`}o686wNi? z;Bgr4Yy<^boatAqkNkp>R$HVzf1fFlA}=WNJyLko@@18zF7i+A0`6Axmm1>kxYtL2 z%v6Rl#sSA1NEdS8p75hM6b&#vgPbCbb}g^b(7sZ-LwE98?*76G+T~jdY5@a;VRG^G z?MsDoRP?X!fL3bHY2aDIt($nJb2%{>@icD@BY5Y}z92pjsw@9ZY%FdlD%TEk1UJCG9_1Ys1cC)LI{IDetPBYGmuc z+!9@38*j}Ovb2CBn&FgrE^NeD$9=sy6mJnOII4tAZ1aSPLmNA+Ughb__T1nV;QozCieG(6rj8V>v66j^8?5Z^;UMmYD*gk{6c0?8KF%G}elSxNtL zv^^L4d)5>Dc-zSl_yBz3a=JCxV-Jq-Jt!=y_rKm4d=;)nTkSr zd_bqs42t4&N<=;s3L3Bk^G>@8E9@{hPqRZs;)ZK|gOA`Cw0am2N0ns}CgEvgJrKOi zf-RhD+f(@%S?Rz=xw$VSu9Keg^&+=oLjWBiAF#Ekjk2I(EkZ_GJ!**-4&}{*xSn-@ zkqUd|z*PYGV1c}Wr6Qx0ihA|-^zko!IzbUnE8;jc$LJw#ss@w<`QBQ1mdTnH7o2Fe z*?bMfdGF0~EcfGwWRSLWx!xV>kDb{QxUTB1e^gzHt4ql%%8>%0`rT<_)r?C|Mjkz4sM*Iq zPm&K{#22bxp^LJ);tFg?(>L-5uw1bX1c{6ti8frS?7yGBuXqV%6?CMZStqVf)-sl~ zSbhOyN47Et(deEcj3nPJ*A*AaqTk29wq_b}6&VXX|L9#;K&3E*oV#p-@fsr5jz0Ki zp$SE-!VMJux4VQ3Jcv$FK{qJhL(jG};515uTm)N<_>_p4y+yYp;mfIOp#e5(KZkp_ z3#>NgzWOF1WQ%_1I|7EXOr#9er;34I!q0z71;dw1UZ$?l$Zoe%QISFaQTL21^9|_QWA(t)Z z-xpG9>*zReH4aWi#*V4OorP;j<`wLyN$(RTs;pA5WN76lh3uifB3cU+=jk%$xc-d2 zUiU}`jXS7OelB`Z2l%!~d%7LYEpN$V1TTeHFMe6evPn$7_;Y5mw0xAz9v&!(Sf3Jh z_0;H_AO}MBn=a%Aqk194o84p&9ov!9W%+bw957s6X~uk)*A2|_>vU}6-r&t$2fF$^ zCAY%IDn?kZfrJ4$Ww$h~*_E!Al0|q~lMtUL^-tZmxXUWzNc_8eNEF_;b%2-`r}|(Ep>XFNA@Vh1hnLxc23LQ;tY@-v_+*H_SG9_Ba)@&oW!TwZCt!04bGZVWK zG``Mz$;>-P?~Tp9LaD|y1vT3_vPzVA=I{G7wi8U$4>MbK>7 z$9SE&CPV%6c7VFl(8@@svP#v&m09G{7z6noj``W$^>gqi+;_MpDqie*HvaVZr@*JqyP0dy`c^Y<|gy*FnSI9!b)jq|-j z4z!L|)2}J<=~if4Fi&qPz#Gb!-D(MbY+7P@Vy+FfpYXv{@~63?;)pH3EpChapiQ>S zN%1aMGGD}P!JdZf9!VyJBaGXkc`?)*KtckmBWIaPDz`QQvH!H7$FFUB!X2WoB%%ao zknrT#IAAt1=jnp`BQ3M}qBGhQ%&AKRC{YhGd3i;k+Xi{C{ z)SqH|dl?^#JGRfNKQ8z5+R{jX7(V|2`{mlwJ^*V8Z^C@N)>T1Fj+OKgBXMt4R%Hgn zhXhUvrmU9Jg^h}&P0#K)=stC^m}R#N7C2OJn&s5D(Vkz(MQ2Y7T1|)l1Lv!J+8F~e zxY9u`{qr_&ck*q!+m>bx%fXA0>WYl;o%Xvawbc6&ck=tKH{y7h_3`DMx(aYcw;|Zd2ifsQ$E zF&++>`xr^{XPJ~RIOz11QK|RbsgNFmt=HK`vVrZ-Bd(s@_W$GVo{Ll^=58`yvj=%6V$sOd00^1&7GbWv?1 z5-ckfYr=kO+&4Bvl}hX!3E~=}X*h*ts-kTDW$f8>|E>-VS1lx4KM+2cVf_CJuS}T? ztq`n!cc~(Yo-sU2{XCs{t-0i8eI5F*2$8uD+Q}6bk_o!_K>E26EEm{`4oeJE$nCc% zl(VHpH?V(S>nc4=b4i=obaQ;`_(|G+Hv%Zb*tp;d2MW?f5qp%>2hMh6t(y(9kY<+c zo9ImlOyqLM3c)@RDiAS|`zUfhq*|4zMvde~DP2(e*a@62gaw!5nIdi$XBxAvVz{7l z&I8rsApKk~THkV_Xbk1|z`?P^SO-4&aJ(ywG(3VT6Cqx*+R23?h*DY6(7cb&pf zJ>I?RhTG@%mhq%uqc`vzy+)cAV>mtIb6&7OI@s4d2LFqj88TW4Z9T5ade%!QG*uM- zj`@&GZ-D>s?THj5(`+$J%=L=l*7o*P*rsx7G`Yn_7-b3TL9F0rzv^3%EE|59aqn?6 zaDrKXvZ@X{Ob6V1w9jg$jB8u0sQoYB10vR?6oTr!PENhyD7iE?y%vh=;PbFJwcaDX zPeLO1{ru^Yp;0TQm;^5_X1q*ZO)t}W)Lt>LX+v=psVPkRk?#=ZN0j(wta^6sXKVE} z5#y+o#VhnE6gV9%D>Oe@TzoxP?-cpC+SJ8x79SEDGUrdAbS?z*zbs%a1yZLW6p7HD z{@G~Fl#VLDLI;LM%90=iiIy0TYE=Z-(`a}=$Gu7fgxba3PS5`!c6~y)NCAbQv>?y0 zi3SP~;t@B!;=wgHuCu`7Ih{TTe+fcWmvP)H?Xzbddb0ohThjUKFD^xvia_^3vZ`mG zk=Z3-)*O`G=3b&c@0h~QLiI@2Gf=}ePUb+x%hiu~fT7U`z-ou|Rd%}*)RK^eCkw0e zMcVl-JRUK$q1>gw6nTk}vkm^S=LQN;wfD{+jDkLsIl|FQ|EkdzCfYL0d^w7}kGKYh zt`+eiHZ7v0li_H7@XJ$W)%Fw+MDCf{+YN5n1@DU<9OvgeO3)54=)K=V{X9&Ea0#XAA;7n{ zK1?>!-eb;uRa1(ns5okDT=Np?nBY%%K7fwpc=TgAkJ--{0Rt|4v8O$G!-|-?%|cf( zTwoA*;(cOak-zuNoT_>bXj0=fV7ww2yUC9F1&r9ylyspI&gVIDVR~)a(!R`7JHi=7 zHd|2gr{)$SLnb9XG)UQyo9~GA%0=KAmNzOTCBj#=W1eVl5C^SAwar*)MR7=2j5|^X zZO1>1sZz1}GBeZsy<)7>M&qpOxmE0Fnim)5La7ZUG%6Sxm)Z4UxTDu8N9N(n&Fb}r z-)8r2tMxxayxPmP+4UCwX5*UgcJX(o-KXp9%eDRgC8gp#>1LN$9nZ0VP*+dIluDI6 zc>}Fxsq#8DI}}T1I<;Z!&1ne>9sB;@ju@gt<+k!0wh0seJhNs~wRY zcvYT;rI4TH@^;Uz3fR+p#;-7k>1ukH*5uc()`6GgapS`;Dw1<@meMho*tf2NX$L+} zHUeuVp-|lo0Az~XNh~``bb7<5*2Xqrjy!LMbJp8lDO>(z-g*ANaYz;#jB@Z ze(X4Yj)wQp@*5&e0H?*s1uYX>1Q6-`iK*Ty%V^XG?eeDCKVBvKr3m0yGv~QY^ARog zWv9m$(xq&YFald*M;wyBz*i8ZfrBp@THjB|92S7I{eB%P7B(Oop>%?zYv{a@=@%SW zu|+7TA88=oLVJ-KCe;*DbXfvG$=U3`_Vk*5!kwBoTB82WD`oek`UK%;}yUSxhO`S z2JTG(hlyWbJo?IZJqM7-tNj2dZ0B<_rw|wh2ES}tMvu0N72?JPY*n3jq3EZw#uR7& zDAjDrJ~bkdkh!~)D#N-O={-Dl_Fk&>*VlKsLl|G^F6=S#e}Df;-Csh>k+%UsQ`|Lq z2sd>4E7U+fV#)Zp5J@d01rSFH6u` z(`k5UL?RP25biZ-?i5u2JMmOAVG&B30h)w7Il3;)v#boIOr>`ucK#0^ts+O^2-sQY z@;8lkD62!bQI9sGne5sYBzZZTpXKJYO(BU_D|)J0kZg+ltAH7xf0%=?_K$VCQ?43KEagk(1gD&yfNzs$!8z4cjemIbTxAi<%_n|q(9?t^Z9OB;l26$iZdeO zrUmF*wsP-fU>{jf7e%BpWFA+T0t2b7aY*;l4>=CcOH0x5i_X`p27|j(*4?@UwO~XD zTGkGL^L}&L{1K;&f2bv1)$~-7(OAJ&o&Nt4Zom#CoaW8jXD7>_0}q2w0{txJ-snlF-X|faWzs= z$Ur;=xkg-U$xAPre*riK-MP*6kCh3Wp*v);?5t3blZCgY3C{|`%?AHM)cY7yBV_Vb zkOR$ig$82kAA*M1|BXP6Uu@0zeEvBQ`_o9S?~E$5Obg51+yxQS}J zBoLXLLi&k^rqE{Hze5$XFmVs2;&?La=!0OYT??cqgPv@71eDZArGj^J8Lg~F4M+1T z+2RUQ0P}}5EQWr@5eQ|E!gZYmiJZx%B|{$$d?|pAZ?^={iPjD|%SEVe0Za%K(JTRb@oQ1^}sFea3IkRh2NMe?c%sl^$r`YJPjm8;?FoHIZ87KQ!c!Y3Jq zVtU~JcoDJ1m{8J`5EstaE1)%4IzNRRTY}k2!}hJSM^Q^A_*2)LW;O6dC#3Gr=x>hrqQXOrAs%4ppW zyQY)R9NGrYshE}3{4Ekv1X7FY9&W9tUcg;{dsbPV%-81eq|w3u)^ez1|D`}4C}u;D zTEQeIv#y`E@=!B{g-JuD=B~tOJ2V#!)^m?fgyy~9NQm|I(b~q|y;q&fDASB)%fu@k ztmME!eRV#3>|bsUj|tTy|LDjc9sIqP}0(tOsvxZs#;k@Omav2nd$9v zo8am$W&9{D)m+%pSOjLl=416F(D2nfj~apG+`=f=4XP$YWvwK7z(JIMT{tHLuDYVwvy0~Iyc|0F1!))-6q4G1&O1R&kC%`Eph z%&_9n@}c48*2%9^r*?Z?rYI?2U-MfKu+147DKr@9N9Qe3ZqAv1hf7(_XROFa0BT(| zAR8oPoZL|J{mbb5WQq~Oy^BhqV1Bkhy0)ZrU9z_b9Lq!Raj;im{)Ik-=H!~*}NTwg?Gj3~r!Cof5e8tF!jDcGZooyF8Mj}6P!5rP@AuHZv`jCr)8av2T%O@SV! z(ENB1&10rHpbcJN2RYhg_g7O~3@(-whuwtQ$tz{s#o8kt!3v~)Jxr&F9&F1%>e+K; zj*dw4^)Epa2}UTU{}@7s5=;)V$)?{O8GWu-h*D??3>jx(xlWhqArU~C=hR`R{nFp# z0EE9m&_q?b0c9*-Ed8oJW^oDhS)u<8#ug`aq3|mK0T8|O9FvcPJYwJ%u> zf2-1I`e^de-R?B=?{3HvFt8SaJ<^P)0eUpfJJ(p2*1Jf)e7Jbd^oIG*`%Sbi6<(oF z1Y#)x(!{C71pMkn8!f72OQv%Bew7?8nZ9xU!y2|prmM`wT-a_g!tI676~%4o0-KOP zC%+)fFk+jLFkKMSWTTspLgF?LXJ+*J>gn?REEa#*L#^cxi8@s4>UH8zI z4AG3k2(ehEIC@i3Ao*0lB^pcX&m4A5yU1xL{P$rYm)iZvCK8}tP7wy#Uy$WvqU%qi zWR(aLCsvS}W_jaWbaV$(ONo_1Zq6r0f(Fa5b`FfdK;;b{nYA|{5E00*TOD97 z>s&SHG;;q<;_kXRWWCt8N%^6?wpAfv`?1>zTqh_P<(i-cB*cAG7-ZF5pZt&#%zLsB z^Mfdgef}Hj>2RruWz*R^c>Tke3mSl5Gy!y7X!>IkIdZp)a_Y%;AC|oj7hwX> z80vPpsw74Bspk0M6VRby+gd7mdwFC+j@3UgBNf(jeCZ+YL3k3?{BQBCQcg+h=8|m* zA9D9#BS1ZK^RT?!O5)7nuf{ot!van2*z7JEv&R~=?;GCpiQ~c2+EC=AB=Yns!t5w7 z_(d3&>deoxuAcVvwXLM!H(kKP(+!uS3Q*+IG5gpoyT$ZM}rKvupVP&11Tylu|PUvQ^ z99FOMwwwz$kntNuFAyJJ?)H+m*T|%$aIY|d0lG$YO1;}95WmzgGZn36t4-aT&*T2W zM~wVF%nyz2L$;zy0U~zy6|n{){?pFU_*D#8i9_}Zgt;m!7K@8y!xXLMMVk+qSWdh~ z8b}}0%Mkk~$*3=}YFo?$nt-T>?phKTf{w0u9W1$p`}dPD~UE9cF~T?i-#fNsGo<1oiaG+$t{cXaTgiVFL}=UeH8 z9(AKLn?B_W=HBF$X(e6$R=XS#OZxSEKK>{)=LAtI0)Y_A+M@gE(0!4TGIP@V=OJ_d zOA=4x{9>veQ*wRtu23ZD#PeERcoTu{&?WMAFB| znxOhga z)UT)>S9`5?L>vb$u<`?Msu{YWD2;TNjR4)PZKeI|w#hMe8~y#qDRu-#Yw+qMwJA@h z8}MYSbvRo*AZ{h~tgY}Y>F)XtB$?b2X=3&9MdF{(^8HH8*e*c8VKURTg?n^nNfjU& zYX}G`I@ewo#_J%Q&m4+tbQG(lpgZVv@Ch zuXEYRO6bDK*C8#X*yb3!Ny{5?+#76TZ*V&#neS z2#a>6=bmP9Nq5uOs1CyP-nTvvK0hC)fQAXe1Fi4FXGW>+hl2qEYy<0{z3Wt-fmtf* z02s0FPG{h4IBJu*4Q7KCPxP)Eh4H%9<$zvb#!i~zmiPW?qiOBkSVuTCP_8i^dwaV6 zxduK+G;vS`fW?BH8v5Hw@TI4h;bi@gT=)^a*A$wt9Pt|r~Bx_0X#$dr$(R?Q#E z*QD^n2Me40FGG15&ldLUaAAD-n%C%*{nB?HU>*rBi#}MEvYP7lJ`quGzn zEe&Uv7#-gV*#Xph@n5{#wrElYPNpR1p@EqGh4^ts076YdihFce2&G!DzXvhU?FN%A z?7XvzoA_~=24&dIzj84b#~68c*;)n!-waNM2}_GNansjsyZ;$e_K>b$cKJ#vqO_z$c4EGF=b&P8J?tUaz-A~t8DgZJR4tM&cu z%5WEs3B2^fb9Qi3kzk95l@$6%dfCu5kb>5LGCvl@!K0IplYiAwDwOmbD*2hQDKRjRskW5 z==4BddE7_JuyH1Ot60B0oK;U6F46qsrsJkpREUYj3)E0Y)omYN3as}QWnW>1=Z22a z4#00&!tOkO=_}gy*K;pGdUL2VE@xxWkAyFHUDJw@`sdJx{92Gxk-jnHx|jyt{GYE? zbCtYSI(k0Ue2S~xQ5u(QhI2Won^{VXv+?b(%XvB1>5ocM3vO_qa^`Eax6V-Mi~mov z9etS8JfS;RLPquhEH!y(jE2qCNo!;P+%_{o#oCHd_ZYD;`a|#G%hmI<)%3IV z_p@~fzirdcc6d*SHuRbo)h^LPCaQ;USbTD%td>@lzgl2hIiYk&zwGJQW7{M!e z&EXNZvLObVnZl+{>>A`;-z|ZQargIti)L{~LEfW;Y8yUp)$P7i1{Rr5W$9*9->TQs zR;#v#+M8jCCDxW05c4ltC_H2gtFQ{wI8EA7Fn3?mGq>6H%3IjvKrC47ca_{u@7?fZ% z{^0FVQ^W=Qn!OM6)#3ghsyJY*jgm!{mwzhWaG0C-<0GM*V!GgecMe2;MC44)84SCi z7?P^>V`CqdlTj=lJKmtffDN&q?ytWzQ~g|k<0`R)Vq`X=JO^$(sTxH^^@Rw6t>)e5 zAeC3WC&;p&MU+789?UHHm750^Tj(x*%T8kV`_JhI8mW+?sUikOV*{9~GiL#0J6BKN z#k#G?>Qp|f$C#MlKyhcp3T*0L_cnzi*XyMPJNbIdiS)%sH!-dxkPxO7qszTQ9BB6l z)buUbo_@4{0^}H~it%?R5M)6#O5X*3PxatuJFhzuA>Zwdh3aqmM&3Raf@r~V>M5aKyZVFg#5aF(f8D$;fga@eSg2y_ zb8JTcxiEiJ6BJuT+65}qIrhD4G7b(qU@(&*B|RY1IBtRUL4J_pCT&h$S*Kq(nPr!F zwqTU1t%^oi0}j(FQ(=HZLE>5>z!78{p8)40Gvq{^@Z1Om zLV{iqZf~UP#gK!Et^QEcPRd3eslN}q>0(+psUU@Y@HrpW{(%8x|F@=Wx}iJ3{g9~` zZvt=m0NrG&3Jtk|JQ4FnPjanUz?<34B!CFsgCJ^PZ@n5`rcoEZ`vCb)qSDF(A1mQu&}m>A9Xa{KQXHtc7()729(>3 z>N=8Pcph!)G>hzmT+}Ecm=kuRA&w2!!NfyKsji)p_`ra%*E+(w7*vA8xPlo82lM;6 z({2WF`Giv<|Es|-yjmD^Q!q29MbpPG$uS@4Gh9(Bj2+SkDwp9*vOf%0N#pDzN7Ay` z1v{k8<}bd1tz|;7z)K8X&|p=< z<^~6a9si7Yw_{vbb$ucNzL1)#+s3C*p~~CPeepsVhxYiq^7)dV{a zgJbJj%Qc6F*vE?04#>9OkK9Q}mw3`pHUP_`MA?ymG48lA!J&8j?q6tc(Jc%D9* z9dXpJD0gvMk<72Butp)58!kWp4a_&qk-7n>`!q{ey`_cXk&eJnZrb!(Z{-7sn=AMQ ziYC&fiX#pWeEIEoCO}E6aS%=r@YDd zkFs?M@YH^M-4^A}n896uaT&A$T812jx4)TF)$@A!0VsUwcz@rJ z>SP}rowa8ZvIgv5rH}o?2!g?x5qCG2&&cs8qlEhr`nZ+#W)ch!=aKPBlrNu0JGpAY zGG~@Sc9$u08f@~$Hh5#@awaq&^Sxj|;1)wx4K~(ga8hiu>E0$ydNOLd>n7k`-n>bZ zORvVpv3W$lI4SYr=xBe%%Sa4}1ZuF3@Vf%mXVF+y#Y|-QY6>2@(5KK+dMvKFdZB67%f*JDq5M{@>pQxFSdHa zgCnfi9WJ8@S^AodlM%K8YTCfp?jz#X7qO7T`T(wBRNN*Zvef19{xDXBKwH@h4s%EA z!^*EN$0W83n9Z-;vnOqA{a8xEsu{kJex%a^MM@V_3KD#mVhSz!l_;wfBhVs&E3iU2 z4?@)NQh3Gp3k%5p4|U}lPcLN^m?5T_=&|Y{64)}y&X^6qoJ&pkt+XzLcXTjs+W|3v z{nq49aU|15Y3OUqN^&#t_6xI?<|lWGW!tYbHj78(_VP zho8I%kFfrCm08(i8p7dX?j}eUmn%0r!*T^fA{8RN3;+uzbk_j4svYl8WgwQPz+Y}6 zM8yMPV=KeF)E;DP6jDIkl7#51*7opQLw^zPrwdZ8@bN5^b=mGh#8dSXUL}vs8!bV! z`{Yx5Vhm<|mlOTh1{^%aRAaot*?6!*^zfva{f(PuZnNV+cVZtSs-qCXS8};;;B0#L ztC%xUdBq;qvX(#~lS{mSPOPJ7^&YJ2^OdX99N5{e!NOu!a(YknC(RX8(5Xvp6~Jyk`4WQBxLmD;Z`zU}WiM{ALuaolULv zRE|NG(NnD3HydB2-7+`|PwG28#;04SDLW-C1|9Xonq{fAew7WY5* zL=L!l_)7J!AwLY^8o$gCuu;GxiP_Hrc;KPoO!~y^S-o`Pr|d_I%Z7oBAO5b4(myt` z4bUQ{5L>WSbjbJY-%r9lI zio~o(1Sj?gQT{+^)Y2*Ktp&flr8Gk0HWkH@x#j0w0}npUgfv->dOA2GOkaA$8YK@^ zjmADWY=LvbxCh_S;XK*eh)R7Q@|?fEeH9w|mPg>EJDUS;zF;%rFqCMg3POCB7rs4x zPfq-i3qeP?sypAxx7Q3dUB(Me{kA@5YeWeQC+{ojv?W{08}k}m;j^q%wfBpLT^Yg@ z3La!>ebn(QR?L(Gs>h=)4PxoCK(=o;p7is4B2hfHSP|h&siV3qD=yq+U5hh-P zSlOl`uy_YDbXjL_5IheV`3pVaOAw$KfHhWI8O@h=eCxYx!JtmUxr9#kKG0J}o;#EW zIt_EXq^(Q$DCpkxr@^1J>r`7T{!0njKR4-I$Vt9gD`t;q3ew=l?5}w{RfooANZE`R z;+UCPotcOMiRzB+{01c(vtd6Dhl#?!EjbqvavjVp1$Nvio-)yV!ckG{4K6tN+bFp> zI;TGnL)g$gA|84erZyTUA;`dInWm)-pRL_IgKWx@ve(HStXYjf6H>uKILt`=-36+9 zaGA3?tnAZ|!Vf7&_=3*rO^3(R;KE9F@MRqN_-YTpI#Xe$k?vQ_H(I@lHJy%8{Bd>+ z2ZOcmXaS-2zBT(L*ZW6cc71%A+emCNNN`oDY94@71~IjnEO%A^MgADv#Yu4Is;x`Ekjlf^xuV>73LjO{Xg^Y@<$m9Q(5)sb+Yu$@<+BVoE}`8mS7GMM!>R~o z2ILF6Q&+75)*vU$?Rlc3OV_C?Mx-h@hCm;!Le5mbH$cA@<=oS`P=+aqUvCM%%T2U! z6S<0o=62E#T06`&M>3mvRPB(SDbAAtnLJheq%x1xMTaisy7Hrt83@Uf<hz7sZdm~80mcA+Hs=WP+ zg#aAWhyc;O{T1RHj!&AXn9HMQA$ygyqIFl9i1JO?20zz+n@0ESZf)8NmyY(C*Gj#K zBEiGsrr z{X`n>Fa%B5uox_J)?3H@#R%*N0E7v53Wg~L37vO_b>r~<+^cAGKLGOn%>#}!E|&RBiYJaG{W`X*c$yF{2h0V5>m!HUu4Gr++%g1vqB{e&Mb=m-tjOaJ zX7+)DIihNXPYh!+U`&#p_f*EN&tc?rvL6~=X-xUpjW`tK0ekx5*UmKd{AYQN+PmXLwqHHUUQ9P8JeE$%4Z=2q7NW z39MW~v}_7F*a45}k>4KE82t!%Qk38ilp64e zHAw$bxLTgmagtk^op-`5eYiR%gYVX~$Oz=VghmQ%(h!#Kw}{sN&5;0-^nqTeZn-(a zU#*y4O&5kzF;7jO6HNt!N+;Y?a|FDh) zV5Iuc*t1jSDid^=K>H+xJjcttbUTRCbK9Y@M^TX~b6 zN~S?SqS{&om89aGC%XocMZ1AC_sr8Q5nI`tqAa!=hCxudeUZqnWu!Y)<$YX@zC8li zy&M*fGG*Jqzj6Yxfh}AyBPg4Jp!WB~jUF;n4z9)~ykhD?rk#uKc)2w+8WMD-RIjD8 z>-AN=m$*>wS4+%C&Gub-k-%{s3%7pB=|l5jWtq0!0?h2>GekI?OPq>hT9Kgf>r&iA z@hex;dlKMbiWuA$1S*WRKY0@ODFWzc5BvpUVQf;xr?yk?hhQ!`3H0o2F+BpWv?4VfVGmKHisco&BE`uQ!6Z6kfVa+a;0fBrW2 z8qA5?6z0H{B2I(~6C4lz9KN(BNV`Bvj<4tFLTXpx!_0Qa?$}Y+-m$*F&$NYQNO*P_ zJt=yM{Yepr5G>7U7dBcoTP8NE#ihCtKZm^W2gXzXDErruP3tjiI<%@EIsX>2wX3xoC`Ha1YJi-IdwKj02+J_n}cTa!Wx-J)yVje z>rLu-M-2A+P1%^UdGi-gBnpcVjEZ`RKH1FZ1&>)G)5kNQ)zqzbhJtwf98U!Jk7MA^ zk{J=i>-*m)h!`~afAwJnB`+-RAEV5)dLu%Gt`vjoQxffQnJ{V$zJ=$G&wzn}=3Mq(5gl@z`h0 z@|D);MSO|QV@uxML$0NMYq1Z_4|d-VnVsc$fBwBwE{k2z!ivvJ_wn`1%JvIJQXKSl zx(*%gNFVnDs+XLtpP0+1y*C;5j!|%~NYE(^bZZFkvGuKLiOO&KpD)$^KXOy+@>9SH*6gnRqOWt zRI1EU?_9p5B4kCMBpR#kBc-Xixnb!#2(r3ckKJFwC!h`Pj8I+)!+fRL1Z>>1YFuqD zxj4H`;m(`Al3%i&t;fa@KaLajx|#^J=m%_=U4C?T>_bfzDVOW{U(YOp+kd{u3^weg zay-wx;>F3LAKSbHwL~x|1$|S{UX5iYcoT7M(s2kAMTfOk&Qz&_^!ZlFt<@>96>|(6 zt@PcDKf$3kP%cd7K$$qssR8lo$=FkOnRS#0fvMr*KMA%>FP@5Yjrye0<;^PeGkK3*a&&ZJmXa_AFeC_b6JS6`zgn3yoG zZaA3~3aZ6$e5bYF4wfOo9gUK#`gp}{(~!>cu0t*Z`gk`}N4N&Bha9ONf5EV+8mSmsfYok8|&zGLpg$^*JYKJ5uwh9M%OO3rbw zdX>@3(6+~f@padc7v(1Vw2=D7bJsmw?Haqu{mqcUTb(zH+`cmhoDlKbD-$p1#gd`3 zo+qxs6%B4Kk5XD7)>R@dAQOo>o9m3GnC_f&djBvAufLS@qm#QLl+RefV5tWg1MCO4 zlrk{(u^$0Ne$%UKM>u}q^kXa6aZSR=2m)zRo_S9v$YS|>d2dOzEfWYC`RAE*_moaI zA=USJpy0{rVNMU$p-kS#vXZy4lMY%1Y>a|&y&=^1HNYAg&x0!Z{k&Td%|Z@A`zMPY z8~`t$H1r2xCWD%#&6Te@#bLprrl$YSanU)FzxCKV!_rD^+wZ>sk3ew0YTvcsI0Bn4THSTBjJ#R7a{o&Xh`7_3g?JRGCICr# zpW>8fVH8(#?}hi(Qw%+1cv+$NZ*N0Yx3yEcEI2*u#TuEmiH0wSx9`Fg0cdjlI*&LAguRi4UPha`EX+aN*g~pQPqE9?7JNo>bxsAs^jU zniv%igoP9}JD*_H$kbtJ5#oH4Gn*h2nePw}h?|71hm~RDM+1V$s(Y(r^F=h*xS+vxC2@O5YmQc(nFeo&?c;R! zWBDx!2@FaE4%i^9>8!a7qE1kOpje_?Cf*-Pyat??Z(h9l8r9{lZyl{ zsTmWzzt}AkrFozo?hZTq>sA+(M+kwt{Z19Uqge>m91&sEVGj6HkiwVH4`wv@y+FAt zV7d}4U;evP3z?)u_HH4*jX6ft)CxW~X1cww8JzWruL8kcK zUEkAk+9&{6#UoX;D|(fr6?YABt@-Q6V+(JGu{bURoArs{c_K@d>PTkCK~T?QcODod zSv^rejk^IXe7UGp*?5*O!OD1HQEyX;%-@*t&7PxR(=cM;vSoy(HS#1%pT$A~I6P6jcXO;N{fzAmYwNv7I_QvGjM@#?J9a64K;^dz zOXpKbMltq85s$S@EF=7Pskfu`&wY3(S+C>pLMjA)yQif?vS(fQrQSwp&4wV{I{;*E zqxl(@Z&xWZ+FG&W+)B$M=b$^B6qk@hP7Ru(5aN`22mgKHE-`K?fA1-Qu3aFEA*CLs zjsqwV;_dQ2leV8~@7%B@cFUZ(4$W}W0o^W!HIXch%6*bm$Xs7qKNVx4dKL1 zy_)QjGp%!*T-ll1DaaKy6~CfZA#JS9mGEX-Q}!|+ikMa7d|>-H4@{j1JdLI(9v7vO z$gj$Jk9&N0rhJcUk;Ujhg&>kR;(P*qkr!2=od_e&{=%lJAf?H%rS2nk^J5^cqaYSl zmo7yTe`*^p@uIq);u;uo&$CgOxb{9Jkxn+S*2VpR?^c1(jFlC{Nc;j zcBRpQy5aezyA5yUIuT|TU=^iR-<4jFVQ5MqC`URIn&KkI#%Nq7ZYZa6}_4&sHy~vzBSJb|4v$#O@9uS z*jOz#nEjd6!jrou|0q3pfGtGL1GVYK58x~(Oc}&b0jKq7?V>S$q3(9f%+U85==Uj< zH2ftP)1C3T>)!CeXrO=pf9rCLy81`a-3>`eT=Sn*%SdU46e2KH9&qTNYlt|xK~Zi` zj@kf>;|X=@Q1SLg#~Z58U{#*SaRHvz-%;mf7PXN>u!u8A2B^*8f;vnDFhx0`z#bLy z)1UZZEhril?(`*J^>({tVve|E=eC%07l1!N21Yv9`QGnQ(R795B$gjdenk+5q{#Ps zZ+JdVK6JW)Tx z>B0OZT|U*eKf(CDf4sFTsl9QI=093oQ+AVpM-<>g<9M3BB`AZJAWI-3M88C!Dr|O@!Kp(uHOdUhOaC2` z+Yj6z2way&q+OW7Zt{rV>Ob@vAi=;k1C5?An!Hg2=MH+s8$Zw+H)|%I-xXg6)d}$f z?C#h`xl`@xvx0x{7s`_fc!Kgm-Q8@RojycA-Ke%+k)n*1rdc)KKoVDBd^4)dTrG zuqhxZ!35MZ?sPJU^aqD~>3!g2L?^NTjFM`=mM zxqh7bX2D&-Z<0>hGo1Sxe*D?3C4k8BOxowWCkB-f(x}Ld#pWprKGnEz|4XF)F>c~4 zl!|A!xi*%6_T=eq46%`s$xqw^RHV21dWqGS8CIBEf;bN`&q*4aovTFp1FENl>zU2b z*!a*|f14#7ZExX~)N}OYumlZp))eNq-8-LzW!~^jJZ0Lm=Vk7cz@TaSFLdoN^UfLI zE)uB(R3rJ9HAitpx_P;MUkbfrxa3+V45*fqS0QJ7JK6DhEXxm+RIp{7tSH;yAJ<>U zo3I?VI0p3rrf*AkhY4Fra1RxQ>0Tk#gu+am($g46kx;cH58wI406uU>gM`1?&WYOC zmNWzblk8RpK;)DpJ}2h`s%9sbJB?5Mr+`J3P$^MT*$@UU&{!|FQv@QMth8ZEKV*2Q zMi;U0`|0A>@Sfi>xKpF_a36q;WQ?$R+XI?reH&wqp1Y5N1P{mO6s2xaPZbxwh^ERH zM{d^FTD7?Glr9V4D2Fa$zU*P}Dl>-boI#(mRk(@X4kKrdzmgwT3tc`$s2S%`!qmuS zLiAKj^~g_BTzGJ#@H#m5b7U;(&pxD*g&{j&JXizM?hIb)98)zTRzWD(mXoS z$cFL%e|W#0_U;i3Rp6Z#uwF*X7#wYNI!@!1JV+i@Jd>>suHj`(659xTtvGl^h21Xn zgqj?UM$NPPm6xh^_+?d~|3U&id90n3Ptg8*>_D>o7nnld8>3QS6h02g8ej4DnC7b5 zTrpx7w6YHnCWx|c&n32iGNG3Dbe1(9fM_`~m6xQjgQ8>)3n<1LrS z$W(|q*Bz$>HUf}xe9rA+A-&=M}G9O^waGvfAS-O!19m@&XX$GXv^K+ab%#O zWHDbY|0FHxin?=_vV?s&Py=V9uAkKa`oURFd5>P~>qI4FY4TX8w?v4k|4Vz5@&3&G zJJ;Y*_bV7x(yyBhj5BLIpwqQ)ho@$6#>0I%%VId=&AKfz!(w=O+4un5fflZu$8<*b z8th`<$*!D_5D6cT@&=s7s+cq(3Szz^)xHBc&Bvv-Pifujj>~Sk0+e29KXhw1H=Cg| zutIIWXRnm=Y)|#r)a;BK_+|ew{v5kGY`=Qd`TO}V>V%Qzh|^sODT6Ia4#ao04lUqH zK}TPH`>^%>hTx#8HG5^(lkMNSL7dy=;I&y57VNjuH&vYdL_T7OH(@dUtP;ekcfeZ9 zgmH}GD)9npI>~uyh0(d-oZGE$PF3?kdD8xjiOE2SHZJRiBXF|0rAuXp&pNP(XStbF zj_K3c>M&Ier0WSTtca(L9A__$;?;WmYOuxTzHLC^Dm|X8uDU-0xTIX3c zU6Ac0!Ln6}6mF@Hu2OQkF*pctwbB#Ln_H<0E`~6=&BOBbBuzNsgv{p;h0_-GOgn-8YhG~)uh&5^=31Xw2mqoIK+ED$g!{Qd&3b|)?( zSHV4!z$$9`g(F6(ar$u7KP8^Bfz-mxm-_}~k3_+?Xwx3>RA?2i=c)m_Jo zmRK=KqWR_(M+0kEPAeI|O27k^5C!f9U82=O67JDuoI(nxhc#I-0PSxONPfdUFDrDE z7`94TYL3eIe!>LKFs3y}oedtOsd-ttF`k&ZzHnnp*Bgnk7g0-;4}SAkWa39?RgJeT zBS^H&+gmbNNtxR;CM5>RC22~U0HZ@^_(%5W`e1tDAnBSJE1vT+u!WAOA#YtmlKqwx zY=~$-+V-Ly7;TuzD?qJy6q~Hyb0ygA;Ydg>^vLy?y%;4O3W2Wyf0`%^J%M7(>UJsr zRCYsnoKI>a0K;}cApy;`V&t5-2`H7s&i8}L;`j>=l+)oO}5P`&8ElD0#Ag1B;am%j(xo4cMlv0u7s{WI51t zQU{5-9LZvRehzx;V(KPAc9S>g44e(ITMBD?puL0qZpnXxO)_NQBX~LUdFoSJJ_-%e z{p*II0+laG2yI;~TA~;2a^Yeu!EX-LjjLQCJNvSf|1mCkI+wdIN)v|p(ZRVCH?aK?4-w1PV<(jIe}D~bgQ61~uyj_r6~`v;>{KBJ3RRnHi@6kVa*no8#B#S4a`sewOY_q2dl^Tm^`$Tc z#X5H#BC?me^kFnBi4+RkmYWaFO0o>RLCR>&Uo1WvCe8t>rEj$z8(EY3T^~yY=g<89 zEh`v0FNR~}tlrsAjPFj>YqxILGC0GPV)6A3X?`V_#(W{13|pjT#P%3D05H>%?oa#E ze-`$Q;nG_vKCGzORSx>%Tyh?J&Eadd|2kdUr8IFnTJAo3?wdD+fv@y}r4{ie%7knw zhq7Vug3Ekpw2V&3D&#ai-BFT(gzs)IEN`6xG7ox=0J4`=nd2XX4H~p4QIqq6+-xsr zm31w)PwfaO^j%f48a3XdbaaTMHUz}WU*(>6$-QM@(Z~5s<~jCz7{)aj56bKhn6#!6 z0kaK1?>>ay)`1dCqO=`2m0{~_vIY_%OTar?LUq+e_t8Je4aTqIS$gn)tRGInf%mqC z!>+!-rA(%52093|DzrY;!M-2Vo_+y__irqU{h62RUw-2(z=8V-z&$0-z$D5k1}^7I z=jQ0*mkexT6-!IB^k}KMAccbQJWAYq{oHwUk!Q8tY02M(-oHb?IuO<8`}n@l)XWL~ zYe(D9MKRe?yi`pWI_idHc*VkL9(kXtZG{SRhnB1Y8P1{cYAmOftvRj^!df`L4*S;4 z+}=vY=^n~ob8am;3b?>avZL8|KdJzLgH~Ct{p`*-ze020%oeb$Xh&3lUzu{0+y!4B z`m!8mx4#J%SL8$#@~)C4XY!HTq#}&{4{RY2)Ic!>7Nf@k{Q>2d)w=S_CeyJ(_Jwt$!%tQP4O~lwk;>P2N5UHm{`fPrmE}?9|HmKzD(Fa_@XyjNyVF+V>a<&2liI<9k|(|tQybew>TI21_Lbnk}X(eja;+05Fu1IwAL*fWFqim z2VCqpx-o;%AZ0e8l}j9t7i&Fhi?)0+)D`90%{CiyT!@Da+mOJ?K6l$-B`2gXHAr_~ z3OuveqqQXjKaa1HOE9Pmi7ehy9|K?i4*vuC|3g&ozkS3hV4w6r;5XWt$#&m}Cg-fx zt^gN1FKETYIT{#=QKApO{|d~w=E}6AwVWJjVjSp`JN0Dfo2w;1fj|A>UYQcjD{DW# z1@S_#Lsd;p8?aUIz>Vw99)r=PufrfIvp=*dL-FG>%G-HD=-dg9k{m^Zy>H^0$E#ND zntl7QN##T-7iMo(biP-mV2^l_E9u#EU!;?Z9PgGRLNVyKhT@;Z_U}p|*tx;7IA_7^ z4qjgcTQ__~KA{r(MC~~Sa~mu^Zho@imK_46`{cM$8;{F@AK5flWo6>{2YIr}*f3g> z=L^t>t#fDkO-I^KIVo^wZ=4-HH9I zexdB8gEe=s9+B-7>H$kQS(BY|(;^|NaLow2@8vEF&7)tVwJ`f-@Cg>VFFzE%!h&>Q+`cglh!{p%@(p40J_rG#1 z){69bX5@3pu=G5??lWw3oJ-x zf0vt}Is8q%54F$Zr0(-njF3duPUIcUuQ-yA ztw*z&3_*)HQet9R)!3uPJX$x;NA)e1zthSINvBS^pP7&gl)+Z4xn*N|hn=z2k*svP zj%Ke--NfomLH9T#;tQj5l0Pw@YZ99ibC555a$@(en^q=$EqHMq%4V1UPmRsk2Ex9x zdD43A5u~2;aqs<1vR9`ouHdE6k?Rq!6Cz1ZXRcaR8|7qh0qC#q`d52;T)f#nM!&K% zK-*zB;`%k*W#3nIy;IvTvK#3Jrq#~W^~P0=#Q5mXOj}v7=Ks$_n`~)=>3mYdMEkJ2GYz@Mbs_!X|NcnX7 zzO#`c7HmGs8AxmD)d8uQ32mmp<&Zv~mEt)mQYdc`lCzrNxv3fVFbw-x`34xT)vs9% zn7LU{1G>3DV2sh2KjLGMD|bG*6f2rwSP@eRsJOY_FV3MUzz)+oQvnBB0@3P$)5Kn z$W2{T&vauz{8LGHbDQe#z6*P897Q+>Ph66^TzwyRboZqMJ6k|ScQL7fWe&$4*<9P5 zzoe>4D+$@vrNUn(fzIvi2I=sB35$!q3MyqRXYM1ftKq%@kVnP?Ket z_)3JY;fF(jPl;&Ao|p^*#I}$ijwP~y1DN9ZtjB^m)f`pAkC>En$ze_!=bxq2B@KS2 z)@zs5o)V3@4`q5Vw5m%3jbRt`>Y0yVQg%hF#_M{=B`4aBsn-fT10qH z`F=-|<}~CCx8z`F(T-l0ac}JGXX7~|@>r>Qo7)9y$Usbl8lk3WhMmuU8GczaQW1)j zMN5WHUydW&d>}+2`k}8LU#K=S5tu8cxfJlB%C|^4q6S9y| z?ah|WO#RqOBvy{jlpZg$f|t_j&oU~W)48C5YP=yqvUzH|dfm{)lL9ucqm*xSJN;3O z!TJn1MG$6{USQv5_M5BWu18;IB^`hBftCPpB7)T=8j$q~IL-P-J6`<-f*!K7O#|QQ zP|-Hra96nLg(tJ>o)A52U8V51q-HP;w8YpA$ZmC5^k3DUVHhel-rU+8I+KFpeOM;b zZr^{t%GJXIK(!iXtUpBJgYU{)$c=}R4w(M+Gh%vhs9)<`LaVz{Qse-pQ-(0Y8kDF3 zCtYyBRH}uwFjs(0rOI~7JVYXoC87QcvF>O#rww5xEx90&a3UMrRKUY+|S~{!C zLQY_fJb{^19KZ9z8yAl=oGjW(8n|l$!O35jew%g3gJYeXTjT8bo+X+B*eQXti?w7{ z*o<^7E*^g0{VxkeoLDd`^&t@>)bdlB&8%UdJhAg-Dz}n~tGtkPcJUTfC49b-z^`1a zGbsq4esAV&8P{WbOS=c*@H$mN4&i zTNa{Pn76sr&^5 zK#EzvcceVhj-p4iUwCIF;fj%6>@=CWuTT}$OVgpY5WaUKS?p8HN8aZS60{D;8G%aC zcJscoCGY!<-Mon=S9~g)aGLe=b`jU&vu241Q(_B48`VW};~fk%pnk9Xi1AF1_||`y ztZUtt>B5Aznurflo2&9#U)sySX#`#4Go9XG*TuYHbT-!}HfjP4rD--LI{O=k?2o$U#(Kw$(5Zdt zXwzJtO^+HiL=!hrjLV4BU+02EdXQc_=Y701)R%Ied^*{&Li^?p>j%!K!&G4pCVBGz`^%QZjnrsZthp$MK; zTS;RA56t>F0s$Z2xGCA_&%sl5iwANP^tB88J}Z0rqikrmE`Ra9ogsZ%C$FD!Uplw# z+5c+R|7x-C?bqGLFq-7Wt%|6fspK2EV;R&4B zlx<39W#BsQ&L8%Ie7#;%HbrMOwgiN^lhy1$=b|;r_8j2CZjPHQKS}Gq{cFAQaxarEjxM^Ru%9`s zlJy7ri;Gkz$Y>}kg$EorMHQuPdN!8udp}uD69n0g^&Sl^A>?@rU$uHzi|fMgpt9ic zAzpfeQM|E47Vw}lm!o@5BPw&~+1ATggf|~f?7vVC$wg8mlP%JYg{1j(nZY&BJbwVp zUH0}5VS_C5JO5o4g}lk!;GF}X{J9v%*qcoLMFY9q8KRqz@oq*)hw};j=8cT`-ZeRu zb0~+U+8W5>9^bf+h1Z_+=FC@rYTsJBP%x2PH0--y8q@|WJ|}2OLOl!e2v0@iu(Qi# z?k*s7f3au=|9|zwNcUD_=Ojanq~!;sM>YbPx8W-p+iadu@g|8MXi0;kUN*;8Ef1B# z2-D`T_&s7pDWcZGziIqPO5Uh^?Ap{Ev`HshgNoTdVbeO|*RN!)>mx@CQSsbqTG|ax8 z2ybW&95uRD1e?w3>m>MyJ=o$8D4eXRazjtK@LLI8=S#7QmuFd&HFaa@N3g*W(E2Of1H^Ae$^MrxXg*A{_ z;$}>i;}SIOE4Dv!C^dw^9WdVOPoAuQ4io!)_k_;lQeCGeOk_}ouE(f~4b0kPa1p%=8MyRMzt19P-)KT@E3NQdW24|3 zSsfiN25E>d#|9G9nkuouLuP0ty~bMg{6LiE@HaGW5G6*uYPWSqb^(=|+GwUXD6F&W zZtJh(JDwf)M1(lhC_X)|nT{Z2^Oa@1b?KT_1JNgwmk4Q4fpXs+?K$^-sT9(3x!n&^ zEb)7f!+y|c=M-DV@I-A1S!olK3KQ%-$R?trgD3^rJ2qCPXewl!bn+HxX*DiG!&K~| z@D|9pDqn3&eCfcV~&3beu+vAZ=Zn)t*oW5ufN<`JxDUo!x-dh7c(W$UYukpC^!`{Xz>`&%}O7&7EN#{9pleGKab3c#;T}5vO zs(Q^<@QVagz&SrlL(2e(@kK|i0261vSrfHPBI>vnKQJY72E^k>$)YP^G0)ZeETdo^ zH;VmG=HDwhY(FkXV9=>ewWTZs4A+H??=mDop=!b6A~LgE1jSE%$UB4b@3wk*6bSQl zdB*3u49kg#nfrTXt#@buPlCMJ38$YA1$*aFkY|qC)s%uNF_1j-E9TM@uqA0ED++{Q zFPdL~ftMw@s4YcTBONY$s5<>Aj0VJ@F@G!%8?Z~!tQ_}p>C9Ru;28}S?f11M=aSaZ ziQ;f4#942v9vp~V{`JX#W06P=K8))xf+Rs72n&1{D(Ch@28NNI;hZ`#2 ze4l!x-C`36IYSsGvRn%C=s=AoF`^gUIl>Z#iY!%<$Up)av3G_LHA4#^-^&qS4J8W) z4s5b4Dz|r4S?ak_;VI?G)r$Wvv`7y!Aja#D)X5-8$q)V*Nab>~ zDWvHo4MRP5Q-0i#)@xJ?WmXb`nRh&`x3o)E7=R(*Ou;w5XmLisZ8n71v=74lS->tS z3%rR)=zmjT@F<2(L<7NL^&I1@v;+FYda=cu#Xy4qi7D()W96?V(#!E`0o#6(yei2= zsD`r!wtC8WB+x5Ehl*B!dJO(wiNCbRv$Cy7W$i1mMDK-_V*$tMdWTxwrYazpp&y`< z0bM*4sJYjeEH3cftdzO$*zuE zM=9&~t8E#?=Ga>uD$f#lFGZzM^65*MO_NoL_(V|+l6^rA*9fI~BZ|Sa11&;k=(w6> zK?Xm(e(V=T>g7?`ZJM}7%zTK<5aJ$u^1*cD`Xot(_;M_0dw;diqQhEU-2VU$6KXZ^ z##`hoRLH>SxWi4Cx}7=EWd9sZ1n<}W;>f=HQ|?tYixoY;r(p>*8mxg=Q+a5RYTlju zV)=r9g4fb3CzTzqj|pH$t7mT=1ze*l7Kq4L&wEdazmd zMQ>&&q7s?P^{Cs2e;FIMAr@wx!;0?u=@QZ902vUuA!kBsrH5YOvpn8Fe=cW5|JtuHZ^QWRXi3&pUXFP(hHcmMGZ~sSS zVq?l4$w@a(Uo?+KuLe-8Dy43a^g)VUne7LMe|(Z!!O z$8=HsMhpLf8wvkO9+wi{|6&5a5W?0GPAv=*Y`_hRPB8vMK=tKxDEc*D;x5b*(E#Sv zn$&hZ(ryR#l(+t4&E0_W-OE1uNzihBpVL!LcmI3y96t&z;I4Ms*wHJ3Hz;)B07}-t zMdBm!2#uffcZyp&>4wFvmmka5PQ{?0SCHIIUexQ-X>(U^EPOhJX7&VrG z$&6<~^Kby?0YfGTlSa$3y{1(-0-R`hvN9d6_j3J=vg^DH^+36{+U3j!EF)6BLRkc1 zLn~=_g&>y|r)c}EGz&^wi{$ur?f)r8bNU5CJX8l>{T5`5q2IiD_%6dhI647W5U+A^ z<(7GEsDm)JB|kg~#qg3xXNn_{;-_(zv)Vhj+Jb4uG1MZ zP=Mhp9rBccdZihWW|aMjqe@K^D^uOqOJY{VCNi~XWtWL9%|1m~oWKB&zLs&in|!`S zY*ENc=|ma6)s`zml7xDz5MuXt$rw;-nig?l*GzMJAkBoIsR)Q&MkR)IOHbD+HQ{JX zer-K38u%vnsLr>%#3L~qXLD!t>7%WGPa3(7oLjNh=SaX{lYi)t%=zRuW)eW2*(Q}IR}JzKJ<`XPr}%C)xr_ukR58=*Bx@N z=YMTohggd_fr>(dop9cS$xpQPl-AMhigA!Yz-*=!OVp-vNsIoHz#1l{jV^|UKPb#U z5ZBzck?rgL-&tLV5++D6zm@P{MAfTkrj||2y-oi@zHXr1JYk&0VeP$UsngQ_D$|P3 zcat%Uqc1{h306Um_WCAVnh~}Br+tVB87dy>a7_ETnvjG>{d<6hN48nht>qEAPCiH| zNwKHMMjzE`wKG=lIqQBx$0PSFQ}p5z{Azy(V(bXx9jT+xKc%`Us-f|{ULs!MGyi3f z;p8)&8BfiFjqJYJ8p(axq_$Ir1Bl`aW=4s5`D{k@jLz&*5gjj1v(839@T?Jh|97h~;0HRRv3k(MEb^3C=ybnp>*A9Qk}iNKI(I6@-~dNB75G4!tN^r*ns ztEPf9CSBglUn<{|H&ykL^FO@%%3S3BGgpc3ZlW7~wDjGv+pb^bbnCHE2ku(iZf!Y$ zxs7EMsD8|vjO?W^gbL%c@Vw-klEj-?E zpgp!Grh)i`%yHpJE4+*!_y#u4#ee-GcqNS03lb!!+FF^$(gqbi%z)cSFhn*hrl=e4 zxO-N{&d3;U#i&m4Tki5a-|Ij6-?Vyx0k+uT#4F*fObh$%ev2RF^qy0Y%+>Y0lKb^G4~u+S*!Euk^E8POotRAR+!Ku1nK@@E6LH33!6?LfzeLot-{JKi`@zhMOJ?+zhML zKP&~m31VtH90iuLEGT4Gpdvv!wt*--c_hIF+r>mfJxfRLwo&&qR@D{|8a^&Iz>hqd zv>824+0|Eu?K5)|-;gvibBmY9!v3M{jzlNA~S07M4rS6psz~#I%r}GN~!hGwg zAd+YicAg_b5ZUI%pTvn!wu9CoNpHAACD-VJ{C6&FM=5k14|KlbaB1uP&JAZ~z_Ap7 znB=G_taKFsQ{q|vPf(5O!n&$@ z(wga0eQ|vl2Z4QI1(EIki#!(#w;P&fEKhmU#=FpRUKscOTJ&sk& zCmQoc_&&iJ2hmDwzxveCm-_DA{b9*417MHr@R^UVm!iz@I+U&)xf9H@=> zgo1t;FM+y=?v_Ob-BTc-pwvn{1&cin#?=%U>7Y($KAb(QSYib}ERLq`_qDmK$GNnj zeBO@zDWKJKjbzbz$INNGh48zkrgyH&{s(5$i*V58jF5D|sC5;*Pq-C?6S+~6BY8H{ zEHUbZvL~~4Sq3h%V>OEzEUouk^~DJLWXKOF(&ru)h!D&H>1-sf80vn!kLQnEwoah( zg-Ree?stV3Jk|QQ598!w#Nugei__RmC8A) zl$4TK+#Hb(o#3F6K!!4AsY2B@X6p;AdRlKAq~-a6R1Zb&&MZ;EQ99?7?BEoWI|{c; zZ5e)S5_Y<%j6*-o4OfBXq`Z*Lkbkc~QMYSvoD@S#kFKsoouAv6vaTV>1r;t^X2aau zvt|0x$`X8rB1wfrrw~NRAse+H#52Z-Gqq)$%AK$b?fe2_-JVD_F}XRBG2vgn#=HfW zKR}e{qA2J86O+by#v+2tq_r%k@fi^C+V^n3vRd7QbdII%bCm!6*GD|_XDEq zQWr)ZTsPMw=1>TXl%l=XjN&cB_INdK8y`v@T%hOIQ;Y$AMDlf zmaQ)|!n?#nTm!oL+5W&;Gu7_otZ^#mbP%jbh)=15)sqQjZ1|kbc;QCp0a@59CJ`+J zU*=9=SbOhuX#NF2o^$JCfdLAOK0EYmOH+jM0QA%Q`gP>WdSfO03|9{CUc~xwScZN; zAFq z4CU=vE7r&G0FNX;^vxuQW=+xWL3oK69}PoOab4^Nkh;L2%)(NW&OO*gD>uw=nF}Af z^u%`8&k-Q~_g@RbDaj-@H-u8UF693f>=cwRF?TP;1ffhdPucZ7jQMOa$B%&Em$@7g zcmSKWr4^OFyPuQ5NTr{I=}P7PM()xhQS4u>PYBMzWrXZ$mmW#4iyP4j8-zA5@CWKI zOb2-RtQ~sYGdEkEV$%KH!*#u(+*+s3A))*dB}~Cc#Phx-r;et`2D);~Qz5+f)(>XR z8`knvG3N>1qO=nQL8HW8Uy=!b-M%xvU8!=eKY0diC*cDbWWFs-UE{@@yc0mqOR4qN z{hYoJ8`gXD8tleh7qcos} z)btlL<`-MF8+Y@4=_x3Q(zZ1YGWJTfy1#`eC=ad0+ozw@BeVhXeOfxNrGo;OWp%;p zlva?c$0Cs=qCA&ay{J6hGF2tuKkE4oRs6eYGg3dr57#XY&&C{|iGT?F=UZRA1qBm1 zzE6IbpVkX5SPIhkm<5pl16Q4-@cLn+Klp!rXUvj2L+fkPF2_rWx^3W=rS&w zyMiE6udF|-Vs(E_YzGbdiKo#{h@2ooA^|y;KC@#5!E1}Y9_wr2j$j+X#Bzc7^XzQp ziw2Nod;5wM;To|LuA{9;TJ{o$X|n!k(E@bbwO6$rS^!)D5J!3jMl4h_oq$=uh||}; z1UN&|r0zh7T<|24>vaM7efnp3`rA>6UCL?+1Gtc<$jo;UbEiYfYR1u`oA69)0M8ye zAV-fqK$m$OYtCRImms2MfD}m8jHUuEJD*4d8z_Ada4g}}v`3Diu}Rygn}`yKsm`Km z8{BX)0fx8LsZOS$1p=VyM~m!Eja<5@V6>gRJ3Ho*LwZQ4;bnllsi$Tcw~*6Cg>=Cn zN}X+(AR&?G0O|w}Xw_>6C9gUHbMR|G)+e#g;s*kc zUYlhgGZ^078G5`n;~32UJMO5Bb#fT#DC&VO%DfC};yidKVYEH@3@yF*ltHSal?ZEA z+q%9Kv)Wwi5`Hp~p8put6_(oDWESA}{-oh%h2)BzaU0a58$G({qks>w?jbmxWJ-*x z6hVw)5#e8r5d(C~Lr2o_a#2<>P~^xhkEa6M>ShncStt+jtv3qfm_5Z3{O_VEYe1P` zFn*Pf>8Z4Faqc=!;Evpz&p6#hHOGz2&e`SVm*_#Vzam2~?Ht}(bm+pw{F5CnU&Ay? z_KZRHT44#3@bR**#G zI+Q0>SANb3-$M|KL$T9BEgbR(`8Sf7uo?21x|{iOYtjE$V(TS4pCH{MAH(6PtUo(G zxNr1msktD9g7Hi^%BuqjVhBDjnZ74~dW5M<=*r7zMfavU43c%v0`tc=o8={uQ=_jJ z9N!Z)1B+$A2_+tyR;F*8gTBHP*vRq6wNv|ip1@616`VEI8?drxY>MARCELRBNY(yc zY9Q7ro!Cm}p8!&>^m4A#3=W6+s_0y$GqF1?iOK%hv)7Jxe)tG(l?xU4f`F<5b_ct) z3biW+^MP|#A&Fa2vF>@Tv+;%8ol$Fan9NWR@N!?!_%{fI_Dq?kuS{(|>ph{Nj>VL7 zhBnbw_)o3$7WfgwTMZMTO3L-b+E;MpwG;{06R*^IYoql`M{+1NwE_V5JDGpZP*GIe z)!U(2X?e}xak{<4DeIMG+5dm)HgrzXg7!k%^0&%Xm*tq_2bvM(G*Gl5j~;>Dwl+qu z6m_6oPWp#N>rJ2=ziul&XDkX!o#23P&K7iSaVf=YS@Vhf;3t^-;U+rOj!%O~F;~My|;R9%o_ci*)@_}gz9oz47h0!}Qe^O3=A(2gn>H3;xPncM5$|32{ zv%ds@zR&sBTb#0m*s}|>X zV=^HZ+ecAj^$q^Kcc%8X{AjBA@@%b3wOoR7Z`u;t!>}1ndjgmE2q}BTxP;+&SKZf$ zGfjqXbeqywWDupe{X}O8l^IvM%fC3=wboyCgZ|Zfl1(;1vM|813kdi%9Y8de(^=l8 zK)%IT+Q`yUjDC9uX*}`F5GcO!+0!?tUuJx%w~@z{CfgbEpgK*t8gVW|X32$A;`&OXO~aWF%w8amvpeAJMyL0!RQ=kb zC-clftG_cLK5s}bDvE=Ssh4kNx&}{0cy>a~j2l+5D|jhyGi96o%bN;-2R6m`;oNDC z5^tLW4Nwr2s6OpFbAvr$FdZs_6Cb-aTNtY^J)6Aac;qRt1T=?=N4LRBh|!1K&MeQA z?>}ZD$ttloN~iMqNgvKfqafXiawOQ7Z}qjkpL)F-l)3M~6`JaM33&%w`vmCbvwVfR z4pcspBfZQ!VOjT~as8V72gD85)KpgHq=K*z!0e2&D!s%#h#+~<3RPYgdYKhTEoVn^ zey(&z|3?1tm2ONcVAQ`cGXv-3Ep;tv%kJHQ`+c%!qwCuN=_(f0Z$+leeq}u89i9oZ z`keD$Hw5`8LA-(CgDYIc0VyRbfvVte(B1e=7ju;2RGGO&rS1HyXCTaHSZ%bx(%KnG;he<{9Ej~r>#Fwx`n)*!>xa=n~AA8V3xnJE0 z*>(|Z`6W!{gg6tMfN|g%JEkd#TR&Ck{}ZAbIi7irW;;Bti6Y}VGZDH2)o<*#Vcjis z=!ZHnNNo2a9V}*pS9QHp+c2^l=?13N&eZ!l#yfr`Oy8wQv2sEhGNHat+iUDx*B@i$ zSnyHnz)C|>NalG!tKEY}h$7^F1oWM$^60}nSDhJLR`7AR`kB-NXRX?OKk8r%ml_|) zrdH!3HMSHpP?l(Br!)CnBiR}pgbOfY+Mf9NM#xW|ev{HUC)i_8z%J-UWzn7JYF#cIxw|-L>*hZg#HBqMYgQloGm! zFi(p%gX6PTzO)P-Z)D~IZ>1QvtUCSK1Q2aD*^_AlR&c%=}!cR z3#pgDh$IXzP4W(stw6KiYBfsD)-^F>N*Kp$C&D|4jker{5jgdC_?Wh0D0WV`N(7^t zX14EF?}egIK4+iYd`7=4iF+um^=og-@EO)flQ;0tq^Jc;^Y zF7n)^tDO~?Kr}*--{&0LSomOx7yM|8;M<%@R7MG8&m^8up<_lNk{ zC~;s?$}l2c8t29BfSLb<(7{&U%;hAlErm&S%#FbCBkZDK?anJpYaCb1EE^jnN)6a$ z1aOpa1C&N}PThU1@Bpd*YM4p-ogG#PYY+JGn5CW|{-7lFFH!by=G-A`ywA zEjqzX#l4FHQVfgpS-JpH@8Xqb%S1r0&?^u#a@bDvf*T+6fuhQ^k*JZ9&>ion=V?+d zLTKcc?=YBqXCg6S{lbV?fS91sY68+@l_oWy<%Ex7{UdD7&D8*@#}n1$9vNz?vqB!t z7kqgjNJw#J8|cWBUb^0}&P}omBVC;bJ*@h4QrX%qXG1o!5KfEpFEqoC!JY`VoLai# zf5!g_(@EDbyniau|4=PPwj~;>v3W(CwKf6>&Y*Hs!;6{REhS7OZ2{d*cgY*2NJTS~ z6Y?MK54p^02K=1kk@9Aq;~dy^b33V2_-FK{?t?-{Eu)q%bZ+Po!9pO-S^5^6k7t_? zIw~1I+$d2odXzh5V5m9$f>aH){jcPiXGMRdvL9n<-wU{xtUwL)azglQ*)!_1c$`Wi z+{g>KSMUiu8QGPWx1FSULSM58O-6v9e7I zwMCIe-=tX4`=#J2xP=5<4C`r1)Cfiuv~d+V``0JU_Cp0Zhfpu?nwsd4VYwerD(q4p z5!nE47vngHpMfXws636D12d3M{LJSF5~4FiiBX|IeGW)@^U(WPKTT?>YF{Q;7fB(x z#k1O`2F~}pf~EInS1_q0g;&}q#14^@NCxCc-1yLOb#4bsHJ{ba71e*4hD7oHm;f`( z#7rN=d3hVD^thkp8nARL`SoSp1G=H8{~++HCw%BVDe$3*+$LyGQO>@`_0M9LM}Ue<-3JxZNUUi;_?y}SvE}zf|7B6(evL3bCbd#xLbYG{YDbW- zpDfAbkbmYM6=+=14979RDpisX+cCd_(I(Bk{Hjq`pxF^&%{QM1+cY@ znnhSehW&i{&HaO)OvyFlIM-$ZwYX>Na?NTYBI-ZFP(w~O|budl0f3wa2Cp0 za5(4%KWY_xgq{SiMt%*W_QGCiicl3k1<98b7;50>EFWiZ+69^0& zo9EmUCE0JN0Of`mX!uRG%kHKUSk(K9#fN-u?6Rl6;i^YSUZi-WShD{a1en z^-v$G@$a8(Uphte^%wPNb@S=E{QV5ypQb;akNNs7`S$PUqketN^FFmI*V2WRE3mm0 zbaKm8SjO|xI4vY)dbCTRk@{H;T`oY7m#ikP{Oz_voH9fzGaNs)J8uRDb*sdQT2H@nxeFg~U z(K(R+aZyk3lKnpD@16MkE7b*^>g@CG@Co=~pUJ{ARe_G?9&$@4TT)nJnpB8hLM?S4st<#_Qg6LOi(?HmEK~~@!{_#&9R z))sP0`=sk2GM$1kS(PzSR;s83B)r%LZ*iI46BA~TX*+`K*34U!{{TOp#>MkevQCu8 zSFJC39Wp-DgyvWZDKO*8b#5Ob7xVHIlZ}>+@?mUsF%O4|2)Ga7A`*1AEQ=yvlAuLJ z_MaRn4WH(QE9bGMyJ|QYxatbO68FU)w*^Nrj0S(+ASsjSy1Iq-qVVpmj@(spkNh?7 zpwm~?eafn}WjWym-Fv6?$f76uMFN+dTGh=_F{z^oZQD_op0Sc4Jmp?~s{J2>^3k}f zivs+ch6)LHV4Z;RGjaZWR*vzq#YkVX&?czG%2U^bZm#(U6E4<{uOW8Tt*M&!>FA?K zh@DuPnj*+zd%zMhjIu$sYs$jxRf5$PHFNbJ}RvSqg+ zRK|F~PqF&S_z7Zue;_@j^0)8aKkbq4@{YX{sQ-=y(I>FFiB15xGIb#k+9AAe9*fqDji$vy! z!61(p=V+N!V%bQNsyH+C7bcQX>9*(mp<+XczPFMi#V3kbGXur8L7#~qJxfdHJuOr4 zyoe7pAZ!H};y5Y$e7UoCDC<8&$Pz|jou;CNk^l(tvg$kLLO;^A?-?ii{3GW1Wip0Q z7o^iz|2(;Jk`oh*lKQ4wJr{;6!UtkU0nqEnES7EOFn)+W2~E?7FEq~5DfxEdRqFhg z@G^Dq(`|e?Y}{2xF}dVHU-_;_FB7E@{-TLKR=Y@~dHw1oVyio961_%spol}a5xxd(T_j-h$$u?alY&oy5A@rF^BVF z_xy3#fwMq=Rbl{16$qBtrz^M4&}_fnA~*~LU2LwFy`9ddUp-oOAkBrMN|S+~TV(l9rH#uov!Hy7_&XTY?Z69C9D<@$>Y zoZSxq7*s6MRdb-0_7x3HkIO{BVTo^_MZesECvVSla;_JcZ@B8yjnjPOmards;qW7y zSZat31qGfSum$uL7Y?Np!`HBY0n_{;jM-V=>pr>v60I(_{G3|9TbpP{EOe*hOBd~u zvo9vkDqAH|J&#eSYGuD;^8&c1*70WR0Ydoqg}!x2X@uN6A8A)-XD>_OuZ*|7Y+sND zf7VD)EwC)X0Rwyz(dPs8mP^}XRz|<; z67BOQ8jROgZQ&`7qt&WRA+6{XDA;f~p6Ce_%{rsqDChJ)(NLAxJs_4TuheH{?qVe-SRx{6!+frxOI1@7fh!Iv zdN#(V#=cNQJH3bT!;Dz-Pj>Ap>NR`vaFGOxpS&e7$_w9Ne?oTW`9r2=v0Qr#r++W1 z#wbq?+wQxJS;UWiZbWtK^_f4Rw6H?m9_O*qG;Y1Ko;)=K_1PE!vkQ3((XJp9a*E{m z4iz1qRY44hb2YWdoI6f}KSytIxPqYPZJ>-o=?NmCM1iBbc-T1&p2lp{4PysaWPwle zd`}n$+&ypDf-SoU3}Ac7ez2qq<0EJm4kl9-Kqf+2Xx7WtXDa~+Lh6`(r(a8>zM#>4 zmBfK!JRboaL#rI{f^oEpmsj~wCg7~u9ZJ&FxFnvHjl9W45{Am73rU(xT_0PnZY{N% zx{R~X*t6uI)vo~7<~;iJaj$S@deDZsHQTTfrgJRhL$wVbtmH!okdoMYn@aQkP1`1wITsnMbhhD^jI@I9HrhFPzLvSHCn9* zrbE5k>ytR#FJebcF(r}6K%%>ak-%_z<(ijzEsY@{P#%ztz{F6wtky{KhDbW?^{O99 zPBI4grDkElP|IOLF&%d6MYwcZ`;~&#(B(26A!nCvFLPcUO6g3AJBI4EgTdH!4SG7v zw4mdrjCNw$0#h9Ad~rrci()h<;5~m+*ASB%^@Cn9flw@(*2t3Zp&)8yG=FUv%|^LnKOf-|3fY`Pi=K zYpavaxSl^bbja^h&t>ku%x?&O`E&kVf%kD83WV5(MLRqkf53KCW^S5Y=955Q1`wtn zPg2dfO0#eEE^9;H2Jr7Oy;lBw-%WoEx&J)BK#Hb_+kj>#E?Ti=YNO#q=M$T#YzIXt zMyg}D#3zdBHXTT#t7@gZaYiY^wj7fs5Xqz}h{ptRu|L6Po?Q8212RG;^ZM{o1t1H2 z{jzniDuLRioO%7`oZpMCuY2z~we#2pp{ML>_Q}`6PN{uX&>QVClwD#^^LXsBs|6<} zQ_4Mm$c}Irf^}i>1!>T0{XYmGhjc(#P6f(AR!?7E7J3vihZrAk;i-HRK?Dmk84g=C zWXw+?5hk-@y~kGoHA4egr@6JdCS^R7Y(8ne=_pmMH(T;6!-`&b2{Ar}W3WN{*WEFF zY=76as=Z^Mpw=k(Wh(wuSJG2#I@y&Bt-oj{ykAFe?vsJB(zRNiBgO zDy2D&kpybj!V@$#a!sHTfw*c(sYgAcX#~F+a&_) zhvjlV@`exiQ#g115MVK9xJ$*YdJRcm>(8jx2JW;Kx3N*w$-z0cpEGUX-3}hAA-6FnXKx(md zv^H>vZWmxUcNJTZeHwZN#J`3Y)wyyPvk$sa04j?h?MpBDGWXLq4{eJPKr9r;oCU(O@G6ufNJFDfVvv`M5 zi0@ju_(gk}ol|8kp$1xQVs4#vw-Qm)epM-ud`ANl@6MNm!}ek4)n9jgC)=3DL{IA1 zmFv}^1^3t}@bV9YQ*AO1tOT@F;q71v_5-yR=ZLs{T;nRlKMfDt zzeZK{^O4zM{uItPs`&pUuWN}=l7EuEO&f@a$Nv}M>bF5vI$UpZ_+?K$QuK8FLedE% z(&i8_oZ$aeQ~w&dV%i?~8Wd=_s%_6Jj7~Bph=Xn_1LGZ$%rUAV2tb3!R=YPuc)~15 zF#Q^QKLYos!X}Z}g30I0AoaJsh3Oc|PMoOZP(QkzZdH@B*=pam2zF`&;(U?%E5Yq{ z6(gHUA43al_ALK&lVi^X{6uKSL@(%_E3^Du#$VO}X{c5@KF)ch+_-kkjwWV%kGJ1K zQV>cc16BG4*s-27iDj0aSoWQ>9_&|%IOVtLhpE&t zy-H}SbT}iOy|U{5W*4SYYGc%+qS6PE0cKjkN(IlDd)OoCzZv#?XB@&Rg@ylBz1ym7 z2NEWTjEPa6xUrrdKp=4Fw&V;vE_E5aX*7jLe-)Kh%fyA5R3(NEKATlngI%Xq?hTcV zV3xe8+>nx0KX<6*`Mr@TLdZgK&hx2?tU|Z&7qvK~eBnd{V4!E9Lyg>82x1W^TKLrS zv^I0wldI?0`~f5s<7J~1wfURo{}dr|_eo99FAw`hmhxH19N#e}yrb(_cB#MKW-z?@ z+TUv;^nWObjSn?ry^C3uK}z=>&#+bXPOf&H=Vhc)YC%_;@sP(A_E<-IV|*QQCWPo- z;Wd-B)0YM{{%!F5s<%lsCJ@}vnd?akJRpODMvT~yMrkq zXzD@g+vXgp#Ri~KqjgLTG$m6y5);>4F98@Fk`r?68y*zvSCGoyPTkfu=`fm(9A~M- zN&a`*?IaHDU?mp3i&Sy2%f0(JPJad_#>;ZMg}|M#JHjO;y6&wn6xS77GTZPImA!u( zn*nX`RktYgSwodL=12cWau#AvP4KwU#opFb<+El7g0blzKfobtH<-BRAqRvyR>iK7 zv6i83?QV=?%1z0#@Tm*21GNYV!fZb$&@_3K!@=D1Pb93`ux?PHM8GhH_ftoOMpC#_r?3Bs{Ft&_mFq%VPjlk88AtM=2GBj~o}Q zO6U}XEEVUULn2VEh0EtOKXG_F#8SFDS;~ zRWk4#RPU0g$GwTPM_5$1yxS3xva`4+J#JCk=9$L^phIP@%PyMz*g}YAgo%I`3%|C4rtU z8wFumCLN8#_4fDDRK;#!SZ4;FEbLbGi@KUjL+3huQfD^5BgJv#?_=1oHosUpYO#H= zU9)Rg9m23sZ=vlgTRYk@?8eQ#2m!n))8S|k;-503jpNsw#WQMxEyBE<@v-XR9V&Zn5CM`kj@#q)#odUVae<2(2J3CKG3~NI@4=yUpsaU8L3Sz+rS)6 zpTN<4zAcfLLcE`hcFRvo+;~E=BfAXX9}NF|hv6J3hNUNJX>Q|H?PPUsvH0BCIJ1SG zfd=dz7;?6-yNEZ#xx1}`RH~pbbw1k2e8dXJRBP7sOV3=*!11|%PvlfZ8}5oKDC|qD zthD==$vt$?O95tJn%t%p_L`m+FiP_%dB*ks0+H6)?PFIzQB?x?&1}oIWvALjSM*%o z9CneHs!GU94D>=x2P;i!D%B)|IQV~>=0$D>&!NU41njfK7ZNzhU#-0QziR#%Os zPDuuuYYBFaD<|`L>QiUz=ef5`aT1V2vV9mFok{TsqT-Y^?vPt&T<+$<03XIrjJ)ub zRJBE|A@c$78l8m}&&~^aj0Gcb=G7b_yaq4-R^6BJ0jEHnf6?>GbEEJ-hK5i6HtR0j zWF^Ns*a;MjzkSj0REqIYog&<@qBQ=O8}M+i%}hGC$rkM9C$qrbKVAPtJK#b|U^f`aa~UQU+x}Yz0Pp=CLvFT z7V=Kn<2D*7Lw%4JQ`wV4?_mU8mgV(;+sAf91lgzmHy{`;r6f@0av9)fe1>rS)?$hM z07Ta{4A0tr4i(GQK|hf0t9qA-Qd6A^$H}TKJpN^kztY>f+P^$p89e)#Dv4|XkHXyL z30adV7&aUg3y2Z5kQ*iZG6K0#4B>r4KGXwd{c@$6O7FHtd~4z3wi}Oso(Ao8zaD|B zCm`=NLlMNm{`GohS9Dy>5&oeF`^QH~tw8r#($K!ggnc$KH#UbY{g$Fzc6O3OhTwoZ zEZGlkh*`$<`E9%cMlTN@+w0DN(Jd=pK~$ME)8=7*{L`i8qal8RjKVJp)_s~eDZ6rs zPnCdCc1rfBK`Cp@!3_ipLDgax{ZNr(1Kxe@czxc-U>w1yj~;3E?xg*$*GIlG^3zh~ z*3Wv;%TNrpF*{^qP7(qIuOLKd%X0Nu1$H*N=CXJGt?~6gJD9UZ@u&e*FFx#>vWYA% zR!#^_cI<}TC@)tqun(9ry-Mgv#J=Rs_Y>+5E;&su_eBc6r1r$VX!KuI)w7f}-BGNv z?jhKA(F=1z_*UdeL}P{LYml`OyVjL$+6HLB^0xi9=k#c)xfD-sadI5E1$kDMtXccn z>pbI;JSqc3n5Vcn(b4=U?Iq#}CkGqoD6vdF(L8FtsXwJ&<375-V2p^V)SQd=T4caNHIpN|;&wM=vMb3<;R5^P?PY3@G=8eG!$ zobQer!Y|KH-pxV7YD<6Fl8QCU33xxqUg_pWRxxlJOUe*g%a9_FsASfL4ZjX#5608cAT45~7WFTqP_D|SOz|Ta3vOP(b&8nb(ad+8?`LSwXxLL+P+P9BPBj%OQ zAF|Q;?F+Nw3HLNV_xrA1aPNHUK?ePXc9ENwTRHez`Z!6JGztnO<@A*RByo0o{TC>I z;fA`)l1SAYm>G0f{2TDOGZTX9G9ttfF_ZqhUs8S56fF1&6-m_b^3Y4?_>jsmmo?uJ z3BBv}RSd&(yMV6Ph>*H4NeWBn87+_=kaC^{8IeIO6kWx?^mqaN>V+k>VDmt0QU6XC zRNyH{e=+tF->1TAoK~zL%rzqYV7Tak+ToT`2}^|Qi)uGrZ}y}@kiMZLfxkSGh!qr( zPM6}i31A8z2=x|^F?M1U0()`DJqNG2oy()hU*Tg-sS zCL{+cT#bE>d0f#**wm=}U-H*6WSpy)@qnVGR1_J_O~v8d&`Uil@vOu@!$+$gCC?<1 z6&h5Qy(6*6g?J;KZ>uZA{(hZh8Lyr7XZ`?$L_c{Agfi=hX(Muv2cGmGbNj^#`?5tFp*gH6gMK%yk(DYqR96_thbIi2CtFK7Vf(xQduHGudOFt z7)F~1$U3izyrRX+ea#<4C=%-4NH4%wvB$OcfT% z2Lj=vf*;W{Li~MxKQfB#zS1_!kmZpNrT{!`yo;EVZEoS+lSv5NY4BTd_-Bz?v;l=b zX@uiocPv{uuO*xZkOs|YJ-f|1G5*6ufV0xaY$pxjFf7XHugK}PviQ>^PGl?w;f+P= z8b%>UtB7(w(b$7Ipw9YH81y3}iUU=IhdHAR^I&`1hvh+VaVAA*K; z{gV2h2a@~tP+8To-tSq%Nm@K zrA=5oIukaRlH!pq(cOJ1qtUT#&ClgUckeJO6H|gp#(8FK3bGgCl*(9<@o}?9LlRVCCIEGygLIsQUi@Fb;^Q4PZt2|h zU}*-Z0neOj=7qJ!oZHO=)R(q&sv~)Iu!blqri>>zW#@Yimh(Dwz$qwaw-)!}A}sY}EC(21Ggs4EhP zp;hRDP5$|MzpFtNXBAY)X0Ut?bPt6$lfX>NzAAGJ zu(cnW(`8TW|2Dk?P)!;Qy1!%X$|d%FrKq|?qhPMs9i+QPfJ^cns(^fI z_phJ%0C^B{r`Un`80!B=3ZEY01@r+{TON&!NS%Uxn}kTftb>-riUczKRQ};@zm3Z$ zMQn%kbTLAEUDwU89tfZ(?lmc&PPDM^(^e8*`)h08-nDE+qX9s!hA(@S8;Y8w28%t= zrsCfJUyfn6`U#h7#Pm}EVaJDjDf>199*6=_Oyw*Jw;;J|pH9gXTP|d2kS zT>y7S3SjM~+Y6-~MY-2=Zi0HJ^{mi-UN!T|A;Bf!gqW|kBWeXeq9rC@r&ohyo@|fk zaRpt~C+taFU>HwGA?{C<+|n8x?{El*xCz=1CDwcZ-jYC2jjMfryDp*5Omx}U_5H?O z?M%NT?5cT@_xhDim>&V};75O-P{vo_xvU#ylk$}he~;f2=jCX#l(k91TdnSmKespV zW9R>DEQ24s$7(nDJpgwa#g4Z0d`VGZ2^zBVew1LB1*9}$NYAAEd-e^3cG?6%A}hDH zR?LAoGeg#^y*GmOS~Q~oxzv>(z#x))ab^Ta#8!p7t)B*W&b45UIz`4Gmovc+8mZ6a zMoLqE`x0yrw()$;za$m7dYoLJJ0z=$3`0L`+>k@hEr=&}b+aO?i%m2nexO;5R%o3i zL)JNZOJ0I$SGH)Ka&224XeCzm%gP_M2*O#nDL zW`gue@vc(6y0u(-N_wxT2zoWXy|AE>Y`W9#^o2jZ$QdTFgP?vuGR)5ZKKS`2o2NZ3 z?rTd2;(r!nDDq`vm6=drKeRt^t-K{osrD~&0=kArt|!T-jat&hjdH<Cl?H=rFtjVvyfX!F;uw=>Ny!v;$~rDkFMe9 z$5%NbgV_VYt%3?jC>rXN`R=B=fzz?|{eOcXtEmqXAQ8mk9wAKd%~NJwUj_*!Llv*{>KHbbju9kH_~Zvvfdw+9mce@D54 zzVthJc3$4*+sJGG6AJfglOA(zr;Q0%{+D2s9g(U)w+_%dl|3ndm-?!+e3jIq`oXZe zKB>p|qr<{A;ap}U?{z*lKJEw}XN+%g@~M$={d~b(^uEQcgwNLNqVf(`O$FTqIbjRC z>g2a}cUI32ua%RSB+<6$MW^1^7DOREI!E>-DJgmwF=zI~fpc;%#uz&_wZgGEAHk9Q z+gR}1D4kfmut{Z&jDw2qyfd$b)l7C{&1*7d(!JA$z27hV*yHzgfE6Zisd7$cfK$aL zU>A~JppOwIFNK!(ApPi5K`p5ArBnX)K_#?I=GB2bz~GZ*$jk@f?618XqB1%Dph*ZE z`+3?@fEGbS5->L9juZIt_m8Hq_CK$_A>ORNZiez+<92zHe2qDf+t+L<+_(db(1gy6 z@#-E$PL_fz}i$_YaxU;bR zM5t$H+cJ=_ Date: Mon, 13 Jun 2016 17:57:34 +0200 Subject: [PATCH 146/268] Fix #1430 "review changes" did misinterpret changes (#1489) Fix #1430: "review changes" did misinterpret changes --- CHANGELOG.md | 1 + .../sf/jabref/model/database/BibDatabase.java | 4 +- .../sf/jabref/model/database/EntrySorter.java | 90 ++----------------- .../model/database/EntrySorterTest.java | 39 ++++++++ 4 files changed, 50 insertions(+), 84 deletions(-) create mode 100644 src/test/java/net/sf/jabref/model/database/EntrySorterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b5f3dfc23aa..7e6b00fb96a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - Fixed [#1476](https://github.com/JabRef/jabref/issues/1476): NPE when importing from SQL DB because of missing DatabaseMode - Fixed [#1481](https://github.com/JabRef/jabref/issues/1481): Mac OS X binary seems broken for JabRef 3.4 release +- Fixed [#1430](https://github.com/JabRef/jabref/issues/1430): "review changes" did misinterpret changes ### Removed diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index 6b8c82b10f3d..e804bd58cb1c 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -110,9 +110,7 @@ public boolean hasEntries() { * sorted by the given Comparator. */ public synchronized EntrySorter getSorter(Comparator comp) { - EntrySorter sorter = new EntrySorter(entries, comp); - eventBus.register(sorter); - return sorter; + return new EntrySorter(new ArrayList<>(getEntries()), comp); } /** diff --git a/src/main/java/net/sf/jabref/model/database/EntrySorter.java b/src/main/java/net/sf/jabref/model/database/EntrySorter.java index e88118fe1d8e..e7cd9fb96321 100644 --- a/src/main/java/net/sf/jabref/model/database/EntrySorter.java +++ b/src/main/java/net/sf/jabref/model/database/EntrySorter.java @@ -15,16 +15,13 @@ */ package net.sf.jabref.model.database; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -import net.sf.jabref.event.EntryAddedEvent; -import net.sf.jabref.event.EntryChangedEvent; -import net.sf.jabref.event.EntryRemovedEvent; import net.sf.jabref.model.entry.BibEntry; -import com.google.common.eventbus.Subscribe; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -32,91 +29,22 @@ public class EntrySorter { private static final Log LOGGER = LogFactory.getLog(EntrySorter.class); - private final List set; + // guarded by itself + private final List entries; private final Comparator comp; - private BibEntry[] entryArray; - private boolean changed; - - public EntrySorter(List entries, Comparator comp) { - set = entries; - this.comp = comp; - changed = true; - index(); - } - - private void index() { - - synchronized (set) { - - // Resort if necessary: - if (changed) { - Collections.sort(set, comp); - changed = false; - } - - // Create an array of IDs for quick access, since getIdAt() is called by - // getValueAt() in EntryTableModel, which *has* to be efficient. - - int count = set.size(); - - - entryArray = new BibEntry[count]; - int piv = 0; - for (BibEntry entry : set) { - entryArray[piv] = entry; - piv++; - } - } + public EntrySorter(List entries, Comparator comparator) { + this.entries = new ArrayList<>(entries); + this.comp = comparator; + Collections.sort(this.entries, comparator); } public BibEntry getEntryAt(int pos) { - synchronized (set) { - return entryArray[pos]; - } + return entries.get(pos); } public int getEntryCount() { - synchronized (set) { - if (entryArray != null) { - return entryArray.length; - } else { - return 0; - } - } - } - - @Subscribe - public void listen(EntryAddedEvent EntryAddedEvent) { - synchronized (set) { - int pos = -Collections.binarySearch(set, EntryAddedEvent.getBibEntry(), comp) - 1; - LOGGER.debug("Insert position = " + pos); - if (pos >= 0) { - set.add(pos, EntryAddedEvent.getBibEntry()); - } else { - set.add(0, EntryAddedEvent.getBibEntry()); - } - } - } - - @Subscribe - public void listen(EntryRemovedEvent entryRemovedEvent) { - synchronized (set) { - set.remove(entryRemovedEvent.getBibEntry()); - changed = true; - } - } - - @Subscribe - public void listen(EntryChangedEvent entryChangedEvent) { - synchronized (set) { - int pos = Collections.binarySearch(set, entryChangedEvent.getBibEntry(), comp); - int posOld = set.indexOf(entryChangedEvent.getBibEntry()); - if (pos < 0) { - set.remove(posOld); - set.add(-posOld - 1, entryChangedEvent.getBibEntry()); - } - } + return entries.size(); } } diff --git a/src/test/java/net/sf/jabref/model/database/EntrySorterTest.java b/src/test/java/net/sf/jabref/model/database/EntrySorterTest.java new file mode 100644 index 000000000000..f4d8be98a0e5 --- /dev/null +++ b/src/test/java/net/sf/jabref/model/database/EntrySorterTest.java @@ -0,0 +1,39 @@ +package net.sf.jabref.model.database; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; + +import net.sf.jabref.model.entry.BibEntry; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class EntrySorterTest { + + @Test + public void testEmptyEntrySorter() throws Exception { + EntrySorter es = new EntrySorter(Collections.emptyList(), Comparator.comparing(BibEntry::getId)); + assertEquals(0, es.getEntryCount()); + } + + @Test + public void testEntrySorterWithOneElement() throws Exception { + BibEntry entryA = new BibEntry("a", "article"); + EntrySorter es = new EntrySorter(Collections.singletonList(entryA), Comparator.comparing(BibEntry::getId)); + assertEquals(1, es.getEntryCount()); + assertEquals(entryA, es.getEntryAt(0)); + } + + @Test + public void testEntrySorterWithTwoElements() throws Exception { + BibEntry entryB = new BibEntry("b", "article"); + BibEntry entryA = new BibEntry("a", "article"); + EntrySorter es = new EntrySorter(Arrays.asList(entryB, entryA), Comparator.comparing(BibEntry::getId)); + assertEquals(2, es.getEntryCount()); + assertEquals(entryA, es.getEntryAt(0)); + assertEquals(entryB, es.getEntryAt(1)); + } + +} From 87389811baa50f750853e2b1fd1de07e10bf13e3 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 14 Jun 2016 10:04:28 +0200 Subject: [PATCH 147/268] Fix NPE issue --- src/main/java/net/sf/jabref/gui/groups/GroupDialog.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index d0e6989c75f1..9ce4a6e21d4c 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -347,7 +347,7 @@ public void actionPerformed(ActionEvent e) { m_sgCaseSensitive.addItemListener(itemListener); // configure for current type - if (editedGroup.getClass() == KeywordGroup.class) { + if (editedGroup != null && editedGroup.getClass() == KeywordGroup.class) { KeywordGroup group = (KeywordGroup) editedGroup; m_name.setText(group.getName()); m_kgSearchField.setText(group.getSearchField()); @@ -356,7 +356,7 @@ public void actionPerformed(ActionEvent e) { m_kgRegExp.setSelected(group.isRegExp()); m_keywordsRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); - } else if (editedGroup.getClass() == SearchGroup.class) { + } else if (editedGroup != null && editedGroup.getClass() == SearchGroup.class) { SearchGroup group = (SearchGroup) editedGroup; m_name.setText(group.getName()); m_sgSearchExpression.setText(group.getSearchExpression()); @@ -364,7 +364,7 @@ public void actionPerformed(ActionEvent e) { m_sgRegExp.setSelected(group.isRegExp()); m_searchRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); - } else if (editedGroup.getClass() == ExplicitGroup.class) { + } else if (editedGroup != null && editedGroup.getClass() == ExplicitGroup.class) { m_name.setText(editedGroup.getName()); m_explicitRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); From 1cda9de96d08b96fcd4e589266acf5c5f3837f70 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 27 Jun 2016 17:38:19 +0200 Subject: [PATCH 148/268] Update gradle from 2.12 to 2.14 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index ca35e388a5c0..7864cf010caf 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ install4j { } task wrapper(type: Wrapper) { - gradleVersion = '2.12' + gradleVersion = '2.14' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c68bd4b82fff..21c4484a7c02 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Mar 15 15:02:24 CET 2016 +#Mon Jun 27 17:21:50 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip From 1b41b07711b9d6479abee50f7228336c30ffd843 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 27 Jun 2016 18:39:15 +0200 Subject: [PATCH 149/268] Update Log4J 2.6 to 2.6.1 (and add it to external-libraries.txt) --- build.gradle | 6 +++--- external-libraries.txt | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 7864cf010caf..2e4355ef04b6 100644 --- a/build.gradle +++ b/build.gradle @@ -105,9 +105,9 @@ dependencies { compile 'com.mashape.unirest:unirest-java:1.4.9' compile 'info.debatty:java-string-similarity:0.13' - compile 'org.apache.logging.log4j:log4j-jcl:2.6' - compile 'org.apache.logging.log4j:log4j-api:2.6' - compile 'org.apache.logging.log4j:log4j-core:2.6' + compile 'org.apache.logging.log4j:log4j-jcl:2.6.1' + compile 'org.apache.logging.log4j:log4j-api:2.6.1' + compile 'org.apache.logging.log4j:log4j-core:2.6.1' testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' diff --git a/external-libraries.txt b/external-libraries.txt index 0d9eb61b217b..e2a892cdc75b 100644 --- a/external-libraries.txt +++ b/external-libraries.txt @@ -87,6 +87,11 @@ Project: Glazed Lists URL: http://www.glazedlists.com/ License: LPGL 2.1! (not explicitly, but no comments in the source header) and MPL +Id: org.apache.logging.log4j +Project: Apache Log2j 2 +URL: http://logging.apache.org/log4j/2.x/ +License: Apache 2.0 + Id: org.apache.pdfbox:fontbox Project: Apache PDFBox URL: http://pdfbox.apache.org From 7269532337031770c4192c1dca7da87d3f9b4996 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 27 Jun 2016 18:43:20 +0200 Subject: [PATCH 150/268] Update mysql-connector-java from 5.1.38 to 5.1.39 --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2e4355ef04b6..1ae1da148e21 100644 --- a/build.gradle +++ b/build.gradle @@ -91,7 +91,9 @@ dependencies { antlr4 'org.antlr:antlr4:4.5.3' compile 'org.antlr:antlr4-runtime:4.5.3' - compile 'mysql:mysql-connector-java:5.1.38' + // VersionEye states that 6.0.3 is the most recent version, but http://dev.mysql.com/downloads/connector/j/ shows that as "Development Release" + compile 'mysql:mysql-connector-java:5.1.39' + compile 'org.postgresql:postgresql:9.4.1208' compile 'net.java.dev.glazedlists:glazedlists_java15:1.9.1' From daacd94e82a5841fa9c8b965877d14abc463328b Mon Sep 17 00:00:00 2001 From: bartsch-dev Date: Tue, 28 Jun 2016 12:00:33 +0200 Subject: [PATCH 151/268] import dialog shows file extensions and filters the view (#1517) --- CHANGELOG.md | 1 + .../sf/jabref/importer/ImportFileFilter.java | 22 +++-- .../jabref/importer/ImportFileFilterTest.java | 84 +++++++++++++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 src/test/java/net/sf/jabref/importer/ImportFileFilterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a0e66edd97c..bbd5f8140a8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Changed - [#1485](https://github.com/JabRef/jabref/issues/1485) Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography +- [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view ### Fixed - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them diff --git a/src/main/java/net/sf/jabref/importer/ImportFileFilter.java b/src/main/java/net/sf/jabref/importer/ImportFileFilter.java index ad2ca2e600c4..5c42c54cb23d 100644 --- a/src/main/java/net/sf/jabref/importer/ImportFileFilter.java +++ b/src/main/java/net/sf/jabref/importer/ImportFileFilter.java @@ -16,6 +16,7 @@ package net.sf.jabref.importer; import java.io.File; +import java.util.StringJoiner; import javax.swing.filechooser.FileFilter; @@ -33,7 +34,12 @@ class ImportFileFilter extends FileFilter implements Comparable getExtensions() { + return Collections.singletonList(".abc"); + } + + @Override + public String getDescription() { + return null; + } + }; + + ImportFileFilter importFileFilter = new ImportFileFilter(importFormatSingleExtension); + assertEquals("Single Extension (*.abc)", importFileFilter.getDescription()); + } + + @Test + public void nameWithMultipleExtensions() { + ImportFormat importFormatMultipleExtensions = new ImportFormat() { + @Override + protected boolean isRecognizedFormat(BufferedReader input) throws IOException { + return false; + } + + @Override + protected ParserResult importDatabase(BufferedReader input) throws IOException { + return null; + } + + @Override + public String getFormatName() { + return "Multiple Extensions"; + } + + @Override + public List getExtensions() { + return Arrays.asList(".abc", ".xyz"); + } + + @Override + public String getDescription() { + return null; + } + }; + + ImportFileFilter importFileFilter = new ImportFileFilter(importFormatMultipleExtensions); + assertEquals("Multiple Extensions (*.abc, *.xyz)", importFileFilter.getDescription()); + } + +} From 756322cf3fba20713bffc8e120a5913a671efb1b Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 28 Jun 2016 12:07:01 +0200 Subject: [PATCH 152/268] Fix email for donations --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ca43e8e5e43..d343578acaf5 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://travis-ci.org/JabRef/jabref.svg?branch=master)](https://travis-ci.org/JabRef/jabref) [![Dependency Status](https://www.versioneye.com/user/projects/557f2723386664002000009c/badge.svg?style=flat)](https://www.versioneye.com/user/projects/557f2723386664002000009c) [![codecov.io](https://codecov.io/github/JabRef/jabref/coverage.svg?branch=master)](https://codecov.io/github/JabRef/jabref?branch=master) -[![Donation](https://img.shields.io/badge/donate-paypal-orange.svg)](https://www.paypal.com/cgi-bin/webscr?item_name=JabRef+Bibliography+Manager&cmd=_donations&lc=US¤cy_code=EUR&business=jabrefmail%40gmail.com) +[![Donation](https://img.shields.io/badge/donate-paypal-orange.svg)](https://www.paypal.com/cgi-bin/webscr?item_name=JabRef+Bibliography+Manager&cmd=_donations&lc=US¤cy_code=EUR&business=donations%40jabref.org) [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/pr)](http://www.issuestats.com/github/jabref/jabref) [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/issue)](http://www.issuestats.com/github/jabref/jabref) From 075a9ca239ede1b6ded5a1b1ce707f8f2d652763 Mon Sep 17 00:00:00 2001 From: Sascha Zeller Date: Tue, 28 Jun 2016 12:23:51 +0200 Subject: [PATCH 153/268] Implement getExtension and getDescription for importers (#1487) * implement getExtension and getDescription * freeciteimporter extensions, remove FILEFORMAT_PATH, add comment to get extensions --- CHANGELOG.md | 1 + .../importer/fileformat/BibTeXMLImporter.java | 13 +++--- .../fileformat/BiblioscapeImporter.java | 10 +++-- .../importer/fileformat/BibtexImporter.java | 8 ++-- .../importer/fileformat/CopacImporter.java | 7 ++-- .../importer/fileformat/EndnoteImporter.java | 9 +++-- .../importer/fileformat/FreeCiteImporter.java | 11 ++--- .../importer/fileformat/ImportFormat.java | 2 +- .../importer/fileformat/InspecImporter.java | 7 ++-- .../importer/fileformat/IsiImporter.java | 12 ++---- .../importer/fileformat/MedlineImporter.java | 11 ++--- .../fileformat/MedlinePlainImporter.java | 7 ++-- .../importer/fileformat/MsBibImporter.java | 7 ++-- .../importer/fileformat/OvidImporter.java | 7 ++-- .../fileformat/PdfContentImporter.java | 24 ++++++++--- .../importer/fileformat/PdfXmpImporter.java | 7 ++-- .../importer/fileformat/RepecNepImporter.java | 35 +++++++--------- .../importer/fileformat/RisImporter.java | 11 ++--- .../fileformat/SilverPlatterImporter.java | 7 ++-- .../OAI2HandlerFetcherTest.java} | 5 +-- .../fileformat/BibTeXMLImporterTest.java | 34 ++++++++++------ .../fileformat/BiblioscapeImporterTest.java | 24 +++++++---- .../fileformat/BibtexImporterTest.java | 13 ++++++ .../fileformat/CopacImporterTest.java | 24 ++++++++--- .../fileformat/EndnoteImporterTest.java | 21 ++++++++-- .../fileformat/FreeCiteImporterTest.java | 36 +++++++++++++++++ .../importer/fileformat/ImportFormatTest.java | 2 - .../importer/fileformat/InspecImportTest.java | 32 +++++++++------ .../importer/fileformat/IsiImporterTest.java | 40 ++++++++----------- .../fileformat/MedlineImporterTest.java | 25 +++++++++--- .../fileformat/MedlinePlainImporterTest.java | 16 ++++++++ .../fileformat/MsBibImporterTest.java | 16 ++++++++ .../importer/fileformat/OvidImporterTest.java | 10 +++++ .../fileformat/PdfContentImporterTest.java | 13 ++++++ .../fileformat/PdfXmpImporterTest.java | 14 +++++-- .../importer/fileformat/RISImporterTest.java | 20 +++++++--- .../fileformat/RepecNepImporterTest.java | 12 +++--- .../fileformat/SilverPlatterImporterTest.java | 10 +++++ .../importer/{fileformat => fetcher}/oai2.xml | 0 .../{fileformat => fetcher}/oai22.xml | 0 .../{fileformat => fetcher}/oai23.xml | 0 41 files changed, 385 insertions(+), 178 deletions(-) rename src/test/java/net/sf/jabref/importer/{fileformat/OAI2ImportTest.java => fetcher/OAI2HandlerFetcherTest.java} (98%) create mode 100644 src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java rename src/test/resources/net/sf/jabref/importer/{fileformat => fetcher}/oai2.xml (100%) rename src/test/resources/net/sf/jabref/importer/{fileformat => fetcher}/oai22.xml (100%) rename src/test/resources/net/sf/jabref/importer/{fileformat => fetcher}/oai23.xml (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbd5f8140a8e..26d697e4a949 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1430](https://github.com/JabRef/jabref/issues/1430): "review changes" did misinterpret changes - Fixed [#1434](https://github.com/JabRef/jabref/issues/1434): Static groups are now longer displayed as dynamic ones - Fixed [#1482](https://github.com/JabRef/jabref/issues/1482): Correct number of matched entries is displayed for refining subgroups +- Fixed [#1444](https://github.com/JabRef/jabref/issues/1444): Implement getExtension and getDescription for importers. ### Removed diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibTeXMLImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BibTeXMLImporter.java index 725b72274a8d..10294622ff99 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibTeXMLImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibTeXMLImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.regex.Pattern; @@ -33,10 +34,10 @@ import org.xml.sax.InputSource; /** - * Importer for the Refer/Endnote format. - * + * Importer for the BibTeXML format. + *

    * check here for details on the format - * http://www.ecst.csuchico.edu/~jacobsd/bib/formats/endnote.html + * http://bibtexml.sourceforge.net/ */ public class BibTeXMLImporter extends ImportFormat { @@ -51,12 +52,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".xml"); } @Override public String getDescription() { - return null; + return "Importer for the BibTeXML format."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java index 29b8d4290c6b..d6fb880586e8 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,7 +29,7 @@ /** * Imports a Biblioscape Tag File. The format is described on - * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm Several + * http://www.biblioscape.com/download/Biblioscape8.pdf Several * Biblioscape field types are ignored. Others are only included in the BibTeX * field "comment". */ @@ -41,12 +42,13 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".txt"); } @Override public String getDescription() { - return null; + return "Imports a Biblioscape Tag File.\n" + + "Several Biblioscape field types are ignored. Others are only included in the BibTeX field \"comment\"."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java index f84f9e8df254..c818142ed61d 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -82,12 +82,14 @@ public String getFormatName() { @Override public List getExtensions() { - return Collections.singletonList("bib"); + return Collections.singletonList(".bib"); } @Override public String getDescription() { - return null; + return "This importer exists only to enable `--importToOpen someEntry.bib`\n" + + "It is NOT intended to import a bib file. This is done via the option action, which treats the metadata fields.\n" + + "The metadata is not required to be read here, as this class is NOT called at --import."; } /** diff --git a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java index 6a058417fc8c..d3e7d1b5e40a 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -17,6 +17,7 @@ import java.io.BufferedReader; import java.io.IOException; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -43,7 +44,7 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".txt"); } @Override @@ -53,7 +54,7 @@ public String getId() { @Override public String getDescription() { - return null; + return "Importer for COPAC format."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java index d597a352a77e..4ad8ca341fde 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,7 +35,7 @@ * journals, e.g., Physical Review Letters, don't use pages anymore) * * check here for details on the format - * http://www.ecst.csuchico.edu/~jacobsd/bib/formats/endnote.html + * http://libguides.csuchico.edu/c.php?g=414245&p=2822898 */ public class EndnoteImporter extends ImportFormat { @@ -50,7 +51,7 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".enw"); } @Override @@ -60,7 +61,7 @@ public String getId() { @Override public String getDescription() { - return null; + return "Importer for the Refer/Endnote format. Modified to use article number for pages if pages are missing."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index 5f654facda35..c62d8b2ff707 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2012, 2015 JabRef contributors. +/* Copyright (C) 2012, 2016 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 @@ -24,10 +24,7 @@ import java.net.URLConnection; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Scanner; +import java.util.*; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; @@ -234,12 +231,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Arrays.asList(".txt",".xml"); } @Override public String getDescription() { - return null; + return "This importer parses text format citations using the online API of FreeCite."; } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java index 41f418328f8a..3df58101cec5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/ImportFormat.java @@ -121,7 +121,7 @@ public static BufferedReader getReader(Path filePath, Charset encoding) * Returns the file extensions that this importer can read. * The extension should contain the leading dot, so for example ".bib" * - * @return list of supported file extensions (not null but may be empty) + * @return list of supported file extensions (not null but may be empty). The list should never be null. Instead return an empty list. */ public abstract List getExtensions(); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java index f60bad7fe4e3..5a7887634db3 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,12 +42,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".txt"); } @Override public String getDescription() { - return null; + return "INSPEC format importer."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java index 5b4db6b86615..08fab164656d 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -17,11 +17,7 @@ import java.io.BufferedReader; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -63,7 +59,7 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Arrays.asList(".isi",".txt"); } @Override @@ -73,7 +69,7 @@ public String getId() { @Override public String getDescription() { - return null; + return "Importer for the ISI Web of Science, INSPEC and Medline format."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java index 4a27483d3cc1..f180264fae6a 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -20,6 +20,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -34,10 +35,10 @@ import org.xml.sax.InputSource; /** - * Importer for the Refer/Endnote format. + * Importer for the Medline format. * * check here for details on the format - * http://www.ecst.csuchico.edu/~jacobsd/bib/formats/endnote.html + * http://www.nlm.nih.gov/bsd/mms/medlineelements.html */ public class MedlineImporter extends ImportFormat { @@ -51,7 +52,7 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Arrays.asList(".nbib", ".xml"); } @Override @@ -61,7 +62,7 @@ public String getId() { @Override public String getDescription() { - return null; + return "Importer for the Medline format."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index 5884b79bbfd7..e416191ef3e2 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -55,12 +56,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Arrays.asList(".nbib", ".txt"); } @Override public String getDescription() { - return null; + return "Importer for the MedlinePlain format."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java index 52d11a7a5d80..2b46ec351567 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MsBibImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2011 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -17,6 +17,7 @@ import java.io.BufferedReader; import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -73,12 +74,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".xml"); } @Override public String getDescription() { - return null; + return "Importer for the MS Office 2007 XML bibliography format."; } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java index de8fe3d3201e..9d4ebebde68b 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -61,12 +62,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".txt"); } @Override public String getDescription() { - return null; + return "Imports an Ovid file."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index 08a885699835..f49d475ce7f6 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -1,3 +1,18 @@ +/* Copyright (C) 2003-2016 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.importer.fileformat; import java.io.BufferedReader; @@ -5,10 +20,7 @@ import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -580,12 +592,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".pdf"); } @Override public String getDescription() { - return null; + return "PdfContentImporter parses data of the first page of the PDF and creates a BibTeX entry. Currently, Springer and IEEE formats are supported."; } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java index 14bb88b624c5..9552dc4fbc8a 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2011 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -19,6 +19,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Path; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -38,7 +39,7 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".pdf"); } @Override @@ -84,7 +85,7 @@ public String getId() { @Override public String getDescription() { - return null; + return "Wraps the XMPUtility function to be used as an ImportFormat."; } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index 04871c5d41e5..a1af94056800 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -1,5 +1,5 @@ /* Copyright (C) 2005 Andreas Rudert - Copyright (C) 2015 JabRef contributors + Copyright (C) 2016 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 @@ -40,21 +40,21 @@ /** * Imports a New Economics Papers-Message from the REPEC-NEP Service. - * + *

    *

    RePEc (Research Papers in Economics) * is a collaborative effort of over 100 volunteers in 49 countries * to enhance the dissemination of research in economics. The heart of * the project is a decentralized database of working papers, journal * articles and software components. All RePEc material is freely available.

    * At the time of writing RePEc holds over 300.000 items.

    - * + *

    *

    NEP (New Economic Papers) is an announcement * service which filters information on new additions to RePEc into edited * reports. The goal is to provide subscribers with up-to-date information * to the research literature.

    - * + *

    *

    This importer is capable of importing NEP messages into JabRef.

    - * + *

    *

    There is no officially defined message format for NEP. NEP messages are assumed to have * (and almost always have) the form given by the following semi-formal grammar: *

    @@ -155,8 +155,8 @@
      * 
    *

    * - * @see NEP * @author andreas_sf at rudert-home dot de + * @see NEP */ public class RepecNepImporter extends ImportFormat { @@ -186,12 +186,7 @@ public List getExtensions() { @Override public String getDescription() { - return - "Imports a New Economics Papers-Message (see http://nep.repec.org)\n" - + "from the REPEC-NEP Service (see http://www.repec.org).\n" - + "To import papers either save a NEP message as a text file and then import or\n" - + "copy&paste the papers you want to import and make sure, one of the first lines\n" - + "contains the line \"nep.repec.org\"."; + return "Imports a New Economics Papers-Message from the REPEC-NEP Service."; } @Override @@ -226,17 +221,17 @@ private void readLine(BufferedReader in) throws IOException { /** * Read multiple lines. - * + *

    *

    Reads multiple lines until either *

      - *
    • an empty line
    • - *
    • the end of file
    • - *
    • the next working paper or
    • - *
    • a keyword
    • + *
    • an empty line
    • + *
    • the end of file
    • + *
    • the next working paper or
    • + *
    • a keyword
    • *
    * is found. Whitespace at start or end of lines is trimmed except for one blank character.

    * - * @return result + * @return result */ private String readMultipleLines(BufferedReader in) throws IOException { StringBuilder result = new StringBuilder(this.lastLine.trim()); @@ -283,7 +278,7 @@ private void parseAuthors(BibEntry be, BufferedReader in) throws IOException { .append(this.lastLine.substring(this.lastLine.indexOf('(') + 1, institutionDone && (this.lastLine .indexOf(')') > (this.lastLine.indexOf('(') + 1)) ? this.lastLine - .indexOf(')') : this.lastLine.length()) + .indexOf(')') : this.lastLine.length()) .trim()); } else { author = this.lastLine.substring(0, this.lastLine.length()).trim(); @@ -363,7 +358,7 @@ private void parseAdditionalFields(BibEntry be, boolean multilineUrlFieldAllowed } else if (keyword.startsWith("Date")) { Date date = null; String content = readMultipleLines(in); - String[] recognizedDateFormats = new String[] {"yyyy-MM-dd", "yyyy-MM", "yyyy"}; + String[] recognizedDateFormats = new String[]{"yyyy-MM-dd", "yyyy-MM", "yyyy"}; int i = 0; for (; (i < recognizedDateFormats.length) && (date == null); i++) { try { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java index 667c2359df96..1863dc617a76 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,8 +32,8 @@ /** * Imports a Biblioscape Tag File. The format is described on - * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm Several - * Biblioscape field types are ignored. Others are only included in the BibTeX + * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm + * Several Biblioscape field types are ignored. Others are only included in the BibTeX * field "comment". */ public class RisImporter extends ImportFormat { @@ -46,12 +47,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".ris"); } @Override public String getDescription() { - return null; + return "Imports a Biblioscape Tag File."; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java index 1a0b43573998..37a7060f98af 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,12 +43,12 @@ public String getFormatName() { @Override public List getExtensions() { - return null; + return Collections.singletonList(".txt"); } @Override public String getDescription() { - return null; + return "Imports a SilverPlatter exported file."; } @Override diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OAI2ImportTest.java b/src/test/java/net/sf/jabref/importer/fetcher/OAI2HandlerFetcherTest.java similarity index 98% rename from src/test/java/net/sf/jabref/importer/fileformat/OAI2ImportTest.java rename to src/test/java/net/sf/jabref/importer/fetcher/OAI2HandlerFetcherTest.java index a73daa091ff9..bef6d7e21b65 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OAI2ImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/OAI2HandlerFetcherTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.importer.fileformat; +package net.sf.jabref.importer.fetcher; import java.io.IOException; @@ -7,7 +7,6 @@ import javax.xml.parsers.SAXParserFactory; import net.sf.jabref.importer.OAI2Handler; -import net.sf.jabref.importer.fetcher.OAI2Fetcher; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; @@ -24,7 +23,7 @@ * @author Christian Kopf * @author Christopher Oezbek */ -public class OAI2ImportTest { +public class OAI2HandlerFetcherTest { protected OAI2Handler handler; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java index 5219196fed48..ae7537746902 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java @@ -1,5 +1,8 @@ package net.sf.jabref.importer.fileformat; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; + import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.DirectoryStream; @@ -10,12 +13,8 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; - -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; - import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; @@ -24,10 +23,11 @@ public class BibTeXMLImporterTest { private final String FILEFORMAT_PATH = "src/test/resources/net/sf/jabref/importer/fileformat"; - + private BibTeXMLImporter importer; /** * Generates a List of all files in the package "/src/test/resources/net/sf/jabref/importer/fileformat" + * * @return A list of Names * @throws IOException */ @@ -40,9 +40,10 @@ public List getTestFiles() throws IOException { } - @BeforeClass - public static void setUp() { + @Before + public void setUp() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); + importer = new BibTeXMLImporter(); } @Test @@ -53,21 +54,28 @@ public void testGetItemsEmpty() { @Test public void testGetFormatName() { - BibTeXMLImporter importer = new BibTeXMLImporter(); Assert.assertEquals("BibTeXML", importer.getFormatName()); } @Test public void testGetCLIId() { - BibTeXMLImporter importer = new BibTeXMLImporter(); Assert.assertEquals("bibtexml", importer.getId()); } @Test - public void testIsRecognizedFormatReject() throws IOException { - BibTeXMLImporter importer = new BibTeXMLImporter(); + public void testsGetExtensions() { + Assert.assertEquals(Collections.singletonList(".xml"), importer.getExtensions()); + } - List list = getTestFiles().stream().filter(n -> !n.getFileName().toString().startsWith("BibTeXMLImporterTest")) + @Test + public void testGetDescription() { + Assert.assertEquals("Importer for the BibTeXML format.", importer.getDescription()); + } + + @Test + public void testIsRecognizedFormatReject() throws IOException { + List list = getTestFiles().stream() + .filter(n -> !n.getFileName().toString().startsWith("BibTeXMLImporterTest")) .collect(Collectors.toList()); for (Path file : list) { diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java index ac7baf87666e..759e740e37f6 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java @@ -3,8 +3,8 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.Collections; - import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; @@ -14,30 +14,40 @@ public class BiblioscapeImporterTest { - private BiblioscapeImporter bsImporter; + private BiblioscapeImporter importer; + @Before public void setUp() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); - bsImporter = new BiblioscapeImporter(); + importer = new BiblioscapeImporter(); } @Test public void testGetFormatName() { - BiblioscapeImporter importer = new BiblioscapeImporter(); Assert.assertEquals(importer.getFormatName(), "Biblioscape"); } + @Test + public void testsGetExtensions() { + Assert.assertEquals(Arrays.asList(".txt"), importer.getExtensions()); + } + + @Test + public void testGetDescription() { + Assert.assertEquals("Imports a Biblioscape Tag File.\n" + + "Several Biblioscape field types are ignored. Others are only included in the BibTeX field \"comment\".", importer.getDescription()); + } + @Test public void testGetCLIID() { - BiblioscapeImporter importer = new BiblioscapeImporter(); Assert.assertEquals(importer.getId(), "biblioscape"); } @Test public void testImportEntriesAbortion() throws Throwable { Path file = Paths.get(BiblioscapeImporter.class.getResource("BiblioscapeImporterTestCorrupt.txt").toURI()); - Assert.assertEquals(Collections.emptyList(), bsImporter.importDatabase(file, Charset.defaultCharset()) - .getDatabase().getEntries()); + Assert.assertEquals(Collections.emptyList(), + importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java index ebfe572d9e27..4e066e672065 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java @@ -5,6 +5,7 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.List; import net.sf.jabref.Globals; @@ -97,4 +98,16 @@ public void testImportEntries() throws IOException, URISyntaxException { public void testGetFormatName() { assertEquals("BibTeX", importer.getFormatName()); } + + @Test + public void testsGetExtensions() { + assertEquals(Arrays.asList(".bib"), importer.getExtensions()); + } + + @Test + public void testGetDescription() { + assertEquals("This importer exists only to enable `--importToOpen someEntry.bib`\n" + + "It is NOT intended to import a bib file. This is done via the option action, which treats the metadata fields.\n" + + "The metadata is not required to be read here, as this class is NOT called at --import.", importer.getDescription()); + } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java index 8ced65c08305..d714527e52a7 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java @@ -17,13 +17,13 @@ import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; public class CopacImporterTest { private final String FILEFORMAT_PATH = "src/test/resources/net/sf/jabref/importer/fileformat"; - + private CopacImporter importer; /** * Generates a List of all files in the package "/src/test/resources/net/sf/jabref/importer/fileformat" @@ -38,14 +38,27 @@ public List getTestFiles() throws IOException { return files; } - @BeforeClass - public static void setUp() { + @Before + public void setUp() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); + importer = new CopacImporter(); + } + + @Test + public void testsGetExtensions() { + List extensions = new ArrayList<>(); + extensions.add(".txt"); + + Assert.assertEquals(extensions.get(0), importer.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + Assert.assertEquals("Importer for COPAC format.", importer.getDescription()); } @Test public void testIsNotRecognizedFormat() throws IOException, URISyntaxException { - CopacImporter importer = new CopacImporter(); List list = getTestFiles().stream().filter(n -> !n.startsWith("CopacImporterTest")) .collect(Collectors.toList()); for (String str : list) { @@ -56,7 +69,6 @@ public void testIsNotRecognizedFormat() throws IOException, URISyntaxException { @Test public void testImportEmptyEntries() throws IOException, URISyntaxException { - CopacImporter importer = new CopacImporter(); Path path = Paths.get(CopacImporterTest.class.getResource("Empty.txt").toURI()); List entries = importer.importDatabase(path, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(Collections.emptyList(), entries); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index da2bd3b85058..fc3540656aa3 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -17,9 +18,7 @@ import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public class EndnoteImporterTest { @@ -42,6 +41,22 @@ public void testGetCLIId() { assertEquals("refer", importer.getId()); } + @Test + public void testsGetExtensions() { + EndnoteImporter importer = new EndnoteImporter(); + List extensions = new ArrayList<>(); + extensions.add(".enw"); + + assertEquals(extensions.get(0), importer.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + EndnoteImporter importer = new EndnoteImporter(); + assertEquals("Importer for the Refer/Endnote format." + + " Modified to use article number for pages if pages are missing.", importer.getDescription()); + } + @Test public void testIsRecognizedFormat() throws IOException, URISyntaxException { List list = Arrays.asList("Endnote.pattern.A.enw", "Endnote.pattern.E.enw", "Endnote.book.example.enw"); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java new file mode 100644 index 000000000000..f60caa6f15b9 --- /dev/null +++ b/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java @@ -0,0 +1,36 @@ +package net.sf.jabref.importer.fileformat; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; + +import java.util.Arrays; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class FreeCiteImporterTest { + + private FreeCiteImporter importer; + + @Before + public void setUp() { + Globals.prefs = JabRefPreferences.getInstance(); + importer = new FreeCiteImporter(); + } + + @Test + public void testGetFormatName() { + assertEquals("text citations", importer.getFormatName()); + } + + @Test + public void testsGetExtensions() { + assertEquals(Arrays.asList(".txt",".xml"), importer.getExtensions()); + } + + @Test + public void testGetDescription() { + assertEquals("This importer parses text format citations using the online API of FreeCite.", importer.getDescription()); + } +} diff --git a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java index a28fd996e779..f3959cc55afd 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java @@ -38,7 +38,6 @@ public void getFormatterNameDoesNotReturnNull() { } @Test - @Ignore public void getExtensionsDoesNotReturnNull() { Assert.assertNotNull(format.getExtensions()); } @@ -62,7 +61,6 @@ public void getIdStripsSpecialCharactersAndConvertsToLowercase() { } @Test - @Ignore public void getDescriptionDoesNotReturnNull() { Assert.assertNotNull(format.getDescription()); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index a423ec33e703..1ccd0e71c341 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -19,18 +19,16 @@ import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public class InspecImportTest { - private InspecImporter inspecImp; + private InspecImporter importer; @Before public void setUp() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); - this.inspecImp = new InspecImporter(); + this.importer = new InspecImporter(); } @Test @@ -38,7 +36,7 @@ public void testIsRecognizedFormatAccept() throws IOException, URISyntaxExceptio List testList = Arrays.asList("InspecImportTest.txt", "InspecImportTest2.txt"); for (String str : testList) { Path file = Paths.get(InspecImportTest.class.getResource(str).toURI()); - assertTrue(inspecImp.isRecognizedFormat(file, Charset.defaultCharset())); + assertTrue(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @@ -49,7 +47,7 @@ public void testIsRecognizedFormatReject() throws IOException, URISyntaxExceptio "IsiImporterTestMedline.isi", "RisImporterTest1.ris", "InspecImportTestFalse.txt"); for (String str : testList) { Path file = Paths.get(InspecImportTest.class.getResource(str).toURI()); - assertFalse(inspecImp.isRecognizedFormat(file, Charset.defaultCharset())); + assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } @@ -68,7 +66,7 @@ public void testCompleteBibtexEntryOnJournalPaperImport() throws IOException, UR expectedEntry.setField("volume", "19"); BibEntryAssert.assertEquals(Collections.singletonList(expectedEntry), - InspecImportTest.class.getResource("InspecImportTest2.txt"), inspecImp); + InspecImportTest.class.getResource("InspecImportTest2.txt"), importer); } @Test @@ -82,7 +80,7 @@ public void importConferencePaperGivesInproceedings() throws IOException { expectedEntry.setField("author", "Prechelt, Lutz"); try (BufferedReader reader = new BufferedReader(new StringReader(testInput))) { - List entries = inspecImp.importDatabase(reader).getDatabase().getEntries(); + List entries = importer.importDatabase(reader).getDatabase().getEntries(); assertEquals(Collections.singletonList(expectedEntry), entries); } } @@ -98,7 +96,7 @@ public void importMiscGivesMisc() throws IOException { expectedEntry.setField("author", "Prechelt, Lutz"); try (BufferedReader reader = new BufferedReader(new StringReader(testInput))) { - List entries = inspecImp.importDatabase(reader).getDatabase().getEntries(); + List entries = importer.importDatabase(reader).getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.get(0); assertEquals(expectedEntry, entry); @@ -107,12 +105,22 @@ public void importMiscGivesMisc() throws IOException { @Test public void testGetFormatName() { - assertEquals("INSPEC", inspecImp.getFormatName()); + assertEquals("INSPEC", importer.getFormatName()); } @Test public void testGetCLIId() { - assertEquals("inspec", inspecImp.getId()); + assertEquals("inspec", importer.getId()); + } + + @Test + public void testsGetExtensions() { + assertEquals(".txt", importer.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + assertEquals("INSPEC format importer.", importer.getDescription()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java index 6d7fe7fd59fd..815220b2d0b8 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java @@ -24,6 +24,8 @@ */ public class IsiImporterTest { + private final IsiImporter importer = new IsiImporter(); + @Rule public ExpectedException thrown = ExpectedException.none(); @@ -40,23 +42,27 @@ public void testParseMonthException() { @Test public void testGetFormatName() { - IsiImporter importer = new IsiImporter(); - Assert.assertEquals(importer.getFormatName(), "ISI"); } @Test public void testGetCLIId() { - IsiImporter importer = new IsiImporter(); - Assert.assertEquals(importer.getId(), "isi"); } @Test - public void testIsRecognizedFormatAccepted() throws IOException, URISyntaxException { + public void testsGetExtensions() { + Assert.assertEquals(Arrays.asList(".isi",".txt"), importer.getExtensions()); + } - IsiImporter importer = new IsiImporter(); + @Test + public void testGetDescription() { + Assert.assertEquals("Importer for the ISI Web of Science, INSPEC and Medline format.", + importer.getDescription()); + } + @Test + public void testIsRecognizedFormatAccepted() throws IOException, URISyntaxException { List list = Arrays.asList("IsiImporterTest1.isi", "IsiImporterTest2.isi", "IsiImporterTestInspec.isi", "IsiImporterTestWOS.isi", "IsiImporterTestMedline.isi"); @@ -68,9 +74,6 @@ public void testIsRecognizedFormatAccepted() throws IOException, URISyntaxExcept @Test public void testIsRecognizedFormatRejected() throws IOException, URISyntaxException { - - IsiImporter importer = new IsiImporter(); - List list = Arrays.asList("IsiImporterTestEmpty.isi"); for (String str : list) { @@ -126,7 +129,6 @@ public void testProcessSubSup() { @Test public void testImportEntries1() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTest1.isi").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); @@ -146,7 +148,6 @@ public void testImportEntries1() throws IOException, URISyntaxException { @Test public void testImportEntries2() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTest2.isi").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(3, entries.size()); @@ -163,7 +164,6 @@ public void testImportEntries2() throws IOException, URISyntaxException { @Test public void testImportEntriesINSPEC() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestInspec.isi").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); @@ -183,16 +183,13 @@ public void testImportEntriesINSPEC() throws IOException, URISyntaxException { a.getField("title")); Assert.assertEquals("article", a.getType()); - Assert.assertEquals("Degl'Innocenti, R. and Guarino, A. and Poberaj, G. and Gunter, P.", - a.getField("author")); + Assert.assertEquals("Degl'Innocenti, R. and Guarino, A. and Poberaj, G. and Gunter, P.", a.getField("author")); Assert.assertEquals("Applied Physics Letters", a.getField("journal")); Assert.assertEquals("2006", a.getField("year")); Assert.assertEquals("#jul#", a.getField("month")); Assert.assertEquals("89", a.getField("volume")); Assert.assertEquals("4", a.getField("number")); - Assert.assertEquals( - "Lorem ipsum abstract", - a.getField("abstract")); + Assert.assertEquals("Lorem ipsum abstract", a.getField("abstract")); Assert.assertEquals("Aip", a.getField("publisher")); Assert.assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals", @@ -202,7 +199,6 @@ public void testImportEntriesINSPEC() throws IOException, URISyntaxException { @Test public void testImportEntriesWOS() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestWOS.isi").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); @@ -260,7 +256,6 @@ public void testIsiAuthorConvert() { @Test public void testImportIEEEExport() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IEEEImport1.txt").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); @@ -269,8 +264,8 @@ public void testImportIEEEExport() throws IOException, URISyntaxException { Assert.assertEquals("article", a.getType()); Assert.assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal")); Assert.assertEquals("Improving Urban Road Extraction in High-Resolution " - + "Images Exploiting Directional Filtering, Perceptual " - + "Grouping, and Simple Topological Concepts", a.getField("title")); + + "Images Exploiting Directional Filtering, Perceptual " + "Grouping, and Simple Topological Concepts", + a.getField("title")); Assert.assertEquals("4", a.getField("volume")); Assert.assertEquals("3", a.getField("number")); Assert.assertEquals("1545-598X", a.getField("SN")); @@ -283,7 +278,6 @@ public void testImportIEEEExport() throws IOException, URISyntaxException { @Test public void testIEEEImport() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IEEEImport1.txt").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); @@ -307,7 +301,6 @@ public void testIEEEImport() throws IOException, URISyntaxException { @Test public void testImportEntriesMedline() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestMedline.isi").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); @@ -344,7 +337,6 @@ public void testImportEntriesMedline() throws IOException, URISyntaxException { @Test public void testImportEntriesEmpty() throws IOException, URISyntaxException { - IsiImporter importer = new IsiImporter(); Path file = Paths.get(IsiImporterTest.class.getResource("IsiImporterTestEmpty.isi").toURI()); List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java index 0dcefbbd835c..a4c47f078a72 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java @@ -36,7 +36,7 @@ @RunWith(MockitoJUnitRunner.class) public class MedlineImporterTest { - private MedlineImporter medlineImporter; + private MedlineImporter importer; private static final String FILEFORMAT_PATH = "src/test/resources/net/sf/jabref/importer/fileformat"; /** @@ -55,7 +55,7 @@ public List getTestFiles() throws IOException { @Before public void setUp() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); - this.medlineImporter = new MedlineImporter(); + this.importer = new MedlineImporter(); } @Test @@ -66,12 +66,27 @@ public void testGetItemsEmpty() { @Test public void testGetFormatName() { - assertEquals("Medline", medlineImporter.getFormatName()); + assertEquals("Medline", importer.getFormatName()); } @Test public void testGetCLIId() { - assertEquals("medline", medlineImporter.getId()); + assertEquals("medline", importer.getId()); + } + + @Test + public void testsGetExtensions() { + List extensions = new ArrayList<>(); + extensions.add(".nbib"); + extensions.add(".xml"); + + assertEquals(extensions.get(0), importer.getExtensions().get(0)); + assertEquals(extensions.get(1), importer.getExtensions().get(1)); + } + + @Test + public void testGetDescription() { + assertEquals("Importer for the Medline format.", importer.getDescription()); } @Test @@ -80,7 +95,7 @@ public void testIsRecognizedFormatReject() throws IOException { .collect(Collectors.toList()); for (Path file : list) { - Assert.assertFalse(file.toString(), medlineImporter.isRecognizedFormat(file, Charset.defaultCharset())); + Assert.assertFalse(file.toString(), importer.isRecognizedFormat(file, Charset.defaultCharset())); } } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index a9ebc8029e06..810efe8fc7b9 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -8,6 +8,7 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -37,6 +38,21 @@ public void setUp() { importer = new MedlinePlainImporter(); } + @Test + public void testsGetExtensions() { + List extensions = new ArrayList<>(); + extensions.add(".nbib"); + extensions.add(".txt"); + + assertEquals(extensions.get(0), importer.getExtensions().get(0)); + assertEquals(extensions.get(1), importer.getExtensions().get(1)); + } + + @Test + public void testGetDescription() { + assertEquals("Importer for the MedlinePlain format.", importer.getDescription()); + } + @Test public void testIsRecognizedFormat() throws IOException, URISyntaxException { List list = Arrays.asList("CopacImporterTest1.txt", "CopacImporterTest2.txt", "IsiImporterTest1.isi", diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java index de4d18d692fd..54543f8df8c7 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java @@ -5,6 +5,7 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -24,6 +25,21 @@ public void setUp() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); } + @Test + public void testsGetExtensions() { + MsBibImporter importer = new MsBibImporter(); + List extensions = new ArrayList<>(); + extensions.add(".xml"); + + Assert.assertEquals(extensions.get(0), importer.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + MsBibImporter importer = new MsBibImporter(); + Assert.assertEquals("Importer for the MS Office 2007 XML bibliography format.", importer.getDescription()); + } + @Test public final void testIsNotRecognizedFormat() throws Exception { MsBibImporter testImporter = new MsBibImporter(); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index 5c0c66f8d570..35f1d8f6eacf 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -40,6 +40,16 @@ public void testGetCLIId() { Assert.assertEquals("ovid", importer.getId()); } + @Test + public void testsGetExtensions() { + Assert.assertEquals(".txt", importer.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + Assert.assertEquals("Imports an Ovid file.", importer.getDescription()); + } + @Test public void testIsRecognizedFormatAccept() throws IOException, URISyntaxException { diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java index 3e853d66c09f..6c39de1e9ebe 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTest.java @@ -5,6 +5,7 @@ import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -16,6 +17,18 @@ public class PdfContentImporterTest { + private final PdfContentImporter importer = new PdfContentImporter(); + + @Test + public void testsGetExtensions() { + assertEquals(Arrays.asList(".pdf"), importer.getExtensions()); + } + + @Test + public void testGetDescription() { + assertEquals("PdfContentImporter parses data of the first page of the PDF and creates a BibTeX entry. Currently, Springer and IEEE formats are supported.", importer.getDescription()); + } + @Test public void doesNotHandleEncryptedPdfs() throws IOException, URISyntaxException { PdfContentImporter importer = new PdfContentImporter(); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index ae3bfd840815..e6338892367f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -17,9 +17,7 @@ import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; public class PdfXmpImporterTest { @@ -37,6 +35,16 @@ public void testGetFormatName() { assertEquals("XMP-annotated PDF", importer.getFormatName()); } + @Test + public void testsGetExtensions() { + assertEquals(".pdf", importer.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + assertEquals("Wraps the XMPUtility function to be used as an ImportFormat.", importer.getDescription()); + } + @Test public void importEncryptedFileReturnsError() throws IOException, URISyntaxException { Path file = Paths.get(PdfXmpImporterTest.class.getResource("/pdfs/encrypted.pdf").toURI()); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java index 75a0f683acc9..f95685db9424 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java @@ -15,29 +15,39 @@ public class RISImporterTest { - private RisImporter risImporter; + private RisImporter importer; @Before public void setUp() { Globals.prefs = JabRefPreferences.getInstance(); - risImporter = new RisImporter(); + importer = new RisImporter(); } @Test public void testGetFormatName() { - Assert.assertEquals(risImporter.getFormatName(), "RIS"); + Assert.assertEquals(importer.getFormatName(), "RIS"); } @Test public void testGetCLIId() { - Assert.assertEquals(risImporter.getId(), "ris"); + Assert.assertEquals(importer.getId(), "ris"); + } + + @Test + public void testsGetExtensions() { + Assert.assertEquals(".ris", importer.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + Assert.assertEquals("Imports a Biblioscape Tag File.", importer.getDescription()); } @Test public void testIfNotRecognizedFormat() throws IOException, URISyntaxException { Path file = Paths.get(RISImporterTest.class.getResource("RisImporterCorrupted.ris").toURI()); - Assert.assertFalse(risImporter.isRecognizedFormat(file, Charset.defaultCharset())); + Assert.assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index 8d3b8082c037..7bd2646a7fda 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -90,12 +90,14 @@ public final void testGetCliId() { Assert.assertEquals("repecnep", testImporter.getId()); } + @Test + public void testGetExtension() { + Assert.assertEquals(".txt", testImporter.getExtensions()); + } + @Test public final void testGetDescription() { - Assert.assertEquals("Imports a New Economics Papers-Message (see http://nep.repec.org)\n" - + "from the REPEC-NEP Service (see http://www.repec.org).\n" - + "To import papers either save a NEP message as a text file and then import or\n" - + "copy&paste the papers you want to import and make sure, one of the first lines\n" - + "contains the line \"nep.repec.org\".", testImporter.getDescription()); + Assert.assertEquals("Imports a New Economics Papers-Message \n" + + "from the REPEC-NEP Service.", testImporter.getDescription()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java index 40950ba27322..3cb41948bafa 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java @@ -41,6 +41,16 @@ public void setUp() throws Exception { bibName = filename + ".bib"; } + @Test + public void testsGetExtensions() { + Assert.assertEquals(".txt", testImporter.getExtensions().get(0)); + } + + @Test + public void testGetDescription() { + Assert.assertEquals("Imports a SilverPlatter exported file.", testImporter.getDescription()); + } + @Parameters(name = "{index}: {0}") public static Collection fileNames() { Object[][] data = new Object[][] {{"SilverPlatterImporterTest1"}, {"SilverPlatterImporterTest2"}}; diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/oai2.xml b/src/test/resources/net/sf/jabref/importer/fetcher/oai2.xml similarity index 100% rename from src/test/resources/net/sf/jabref/importer/fileformat/oai2.xml rename to src/test/resources/net/sf/jabref/importer/fetcher/oai2.xml diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/oai22.xml b/src/test/resources/net/sf/jabref/importer/fetcher/oai22.xml similarity index 100% rename from src/test/resources/net/sf/jabref/importer/fileformat/oai22.xml rename to src/test/resources/net/sf/jabref/importer/fetcher/oai22.xml diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/oai23.xml b/src/test/resources/net/sf/jabref/importer/fetcher/oai23.xml similarity index 100% rename from src/test/resources/net/sf/jabref/importer/fileformat/oai23.xml rename to src/test/resources/net/sf/jabref/importer/fetcher/oai23.xml From 6eccd505f8a0ec55500e7b411e7feabc0d4d44d7 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 28 Jun 2016 12:34:19 +0200 Subject: [PATCH 154/268] Fix imports. --- .../net/sf/jabref/importer/fetcher/SpringerFetcher.java | 4 ++-- .../sf/jabref/importer/fileformat/FreeCiteImporter.java | 6 +++++- .../net/sf/jabref/importer/fileformat/IsiImporter.java | 7 ++++++- .../sf/jabref/importer/fileformat/PdfContentImporter.java | 6 +++++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java index 566939a07566..6c3015387923 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java @@ -19,8 +19,8 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFiles; -import net.sf.jabref.importer.ImportInspector; + import net.sf.jabref.gui.help.HelpFiles; + import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.JSONEntryParser; import net.sf.jabref.logic.l10n.Localization; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index c62d8b2ff707..cd53d1226651 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -24,7 +24,11 @@ import java.net.URLConnection; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Scanner; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java index 08fab164656d..d61adf70c487 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java @@ -17,7 +17,12 @@ import java.io.BufferedReader; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index f49d475ce7f6..3e6c49a78229 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -20,7 +20,11 @@ import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; From d3e0371c6d5f72fdc03c1e1f24747ef5d02eecd3 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 28 Jun 2016 12:46:33 +0200 Subject: [PATCH 155/268] Fix imports again (for the tests). --- .../jabref/importer/fileformat/BibTeXMLImporterTest.java | 7 ++++--- .../importer/fileformat/BiblioscapeImporterTest.java | 1 + .../sf/jabref/importer/fileformat/EndnoteImporterTest.java | 4 +++- .../jabref/importer/fileformat/FreeCiteImporterTest.java | 3 ++- .../sf/jabref/importer/fileformat/ImportFormatTest.java | 1 - .../sf/jabref/importer/fileformat/InspecImportTest.java | 4 +++- .../sf/jabref/importer/fileformat/PdfXmpImporterTest.java | 4 +++- 7 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java index ae7537746902..4f069e9a6754 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java @@ -1,8 +1,5 @@ package net.sf.jabref.importer.fileformat; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; - import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.DirectoryStream; @@ -13,6 +10,10 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java index 759e740e37f6..086aeeccc857 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java @@ -5,6 +5,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; + import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index fc3540656aa3..9c409fdde315 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -18,7 +18,9 @@ import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class EndnoteImporterTest { diff --git a/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java index f60caa6f15b9..f46fb9aaa137 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java @@ -1,9 +1,10 @@ package net.sf.jabref.importer.fileformat; +import java.util.Arrays; + import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import java.util.Arrays; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java index f3959cc55afd..39f412bb5ebd 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/ImportFormatTest.java @@ -6,7 +6,6 @@ import java.util.regex.Pattern; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index 1ccd0e71c341..7b9880b05ea9 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -19,7 +19,9 @@ import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class InspecImportTest { diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index e6338892367f..211dbd59de0d 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -17,7 +17,9 @@ import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class PdfXmpImporterTest { From c0c49f045a3095bce4cf0810eb81d58a6c01cb20 Mon Sep 17 00:00:00 2001 From: Matthias Geiger Date: Tue, 28 Jun 2016 12:59:18 +0200 Subject: [PATCH 156/268] Update template to refer to discourse.jabref.org --- .github/ISSUE_TEMPLATE.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 8dcd05a16e22..a8733ff92096 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,8 @@ -JabRef version on + + +JabRef version on Steps to reproduce: From 6cff0cbf48ffb25dc87f9dd2248a32ed84c293ef Mon Sep 17 00:00:00 2001 From: Matthias Geiger Date: Tue, 28 Jun 2016 13:03:16 +0200 Subject: [PATCH 157/268] Add pointers to discourse.jabref.org --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d343578acaf5..dedc17e23e0e 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,10 @@ JabRef can be run as a command line application to convert from any import forma ### Bug Reports, Suggestions, Other Feedback We are thankful for any bug reports or other feedback. -If there are features you want included in JabRef, tell us! + +If there are features you want included in JabRef, [tell us in our forum](http://discourse.jabref.org/c/features)! + +If you have questions regarding the usage, or you want to give general feedback the forum is also the right place for this: [discourse.jabref.org](http://discourse.jabref.org/c/features) You can use our [GitHub issue tracker](https://github.com/JabRef/jabref/issues) to send in bug reports and suggestions. From af18243b204495c0298ff73e578ad58e7f8c0b03 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Tue, 28 Jun 2016 13:07:47 +0200 Subject: [PATCH 158/268] Fix tests --- .../jabref/importer/fileformat/RepecNepImporterTest.java | 6 +++--- .../SilverPlatterImporterTestNotRecognized.java | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index 7bd2646a7fda..7bc2f9912f86 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -7,6 +7,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.Collections; import java.util.List; import net.sf.jabref.Globals; @@ -92,12 +93,11 @@ public final void testGetCliId() { @Test public void testGetExtension() { - Assert.assertEquals(".txt", testImporter.getExtensions()); + Assert.assertEquals(Collections.singletonList(".txt"), testImporter.getExtensions()); } @Test public final void testGetDescription() { - Assert.assertEquals("Imports a New Economics Papers-Message \n" - + "from the REPEC-NEP Service.", testImporter.getDescription()); + Assert.assertEquals("Imports a New Economics Papers-Message from the REPEC-NEP Service.", testImporter.getDescription()); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java index 6e11e7503fb3..3efd7b9ab907 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java @@ -1,5 +1,6 @@ package net.sf.jabref.importer.fileformat; +import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; @@ -13,6 +14,8 @@ import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertNotNull; + public class SilverPlatterImporterTestNotRecognized { public SilverPlatterImporter testImporter; @@ -26,10 +29,12 @@ public void setUp() throws Exception { @Test public final void testIsNotRecognizedFormat() throws Exception { - List notAccept = Arrays.asList("emptyFile.xml", "IsiImporterTest1.isi", "oai2.xml", + List notAccept = Arrays.asList("emptyFile.xml", "IsiImporterTest1.isi", "RisImporterTest1.ris", "InspecImportTest2.txt"); for (String s : notAccept) { - Path file = Paths.get(SilverPlatterImporter.class.getResource(s).toURI()); + URL resource = SilverPlatterImporter.class.getResource(s); + assertNotNull("resource " + s + " must be available", resource); + Path file = Paths.get(resource.toURI()); Assert.assertFalse(testImporter.isRecognizedFormat(file, Charset.defaultCharset())); } } From 40f16313cfb0f544a4ccbe46a70e66a9b1c8e1d0 Mon Sep 17 00:00:00 2001 From: bartsch-dev Date: Tue, 28 Jun 2016 14:09:57 +0200 Subject: [PATCH 159/268] test ImportFileFilter with Mockito (#1522) --- .../jabref/importer/ImportFileFilterTest.java | 64 +++---------------- 1 file changed, 9 insertions(+), 55 deletions(-) diff --git a/src/test/java/net/sf/jabref/importer/ImportFileFilterTest.java b/src/test/java/net/sf/jabref/importer/ImportFileFilterTest.java index 5823c58230e1..b624f96c401f 100644 --- a/src/test/java/net/sf/jabref/importer/ImportFileFilterTest.java +++ b/src/test/java/net/sf/jabref/importer/ImportFileFilterTest.java @@ -1,48 +1,25 @@ package net.sf.jabref.importer; -import java.io.BufferedReader; -import java.io.IOException; import java.util.Arrays; import java.util.Collections; -import java.util.List; import net.sf.jabref.importer.fileformat.ImportFormat; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class ImportFileFilterTest { @Test public void nameWithSingleExtensions() { - ImportFormat importFormatSingleExtension = new ImportFormat() { - @Override - protected boolean isRecognizedFormat(BufferedReader input) throws IOException { - return false; - } - - @Override - protected ParserResult importDatabase(BufferedReader input) throws IOException { - return null; - } - - @Override - public String getFormatName() { - return "Single Extension"; - } - - @Override - public List getExtensions() { - return Collections.singletonList(".abc"); - } - - @Override - public String getDescription() { - return null; - } - }; + ImportFormat importFormatSingleExtension = mock(ImportFormat.class); + when(importFormatSingleExtension.getFormatName()).thenReturn("Single Extension"); + when(importFormatSingleExtension.getExtensions()).thenReturn(Collections.singletonList(".abc")); ImportFileFilter importFileFilter = new ImportFileFilter(importFormatSingleExtension); assertEquals("Single Extension (*.abc)", importFileFilter.getDescription()); @@ -50,32 +27,9 @@ public String getDescription() { @Test public void nameWithMultipleExtensions() { - ImportFormat importFormatMultipleExtensions = new ImportFormat() { - @Override - protected boolean isRecognizedFormat(BufferedReader input) throws IOException { - return false; - } - - @Override - protected ParserResult importDatabase(BufferedReader input) throws IOException { - return null; - } - - @Override - public String getFormatName() { - return "Multiple Extensions"; - } - - @Override - public List getExtensions() { - return Arrays.asList(".abc", ".xyz"); - } - - @Override - public String getDescription() { - return null; - } - }; + ImportFormat importFormatMultipleExtensions = mock(ImportFormat.class); + when(importFormatMultipleExtensions.getFormatName()).thenReturn("Multiple Extensions"); + when(importFormatMultipleExtensions.getExtensions()).thenReturn(Arrays.asList(".abc", ".xyz")); ImportFileFilter importFileFilter = new ImportFileFilter(importFormatMultipleExtensions); assertEquals("Multiple Extensions (*.abc, *.xyz)", importFileFilter.getDescription()); From e060aa29ec47ba245e334809b42f84674068b359 Mon Sep 17 00:00:00 2001 From: bartsch-dev Date: Tue, 28 Jun 2016 14:10:03 +0200 Subject: [PATCH 160/268] create update checker for the enduser (#1459) --- src/main/java/net/sf/jabref/JabRefGUI.java | 10 ++ .../java/net/sf/jabref/JabRefPreferences.java | 8 +- .../java/net/sf/jabref/cli/JabRefCLI.java | 15 ++ .../java/net/sf/jabref/gui/JabRefFrame.java | 9 +- .../gui/actions/SearchForUpdateAction.java | 35 ++++ .../sf/jabref/gui/desktop/JabRefDesktop.java | 38 +++++ .../net/sf/jabref/gui/help/HelpAction.java | 11 +- .../sf/jabref/gui/help/NewVersionDialog.java | 110 +++++++++++++ .../jabref/gui/menus/help/DonateAction.java | 14 +- .../gui/menus/help/ForkMeOnGitHubAction.java | 16 +- .../sf/jabref/gui/worker/VersionWorker.java | 101 ++++++++++++ .../net/sf/jabref/logic/util/BuildInfo.java | 18 +- .../net/sf/jabref/logic/util/Version.java | 154 ++++++++++++++++++ .../jabref/logic/util/VersionPreferences.java | 40 +++++ src/main/java/osx/macadapter/MacAdapter.java | 2 +- src/main/resources/l10n/JabRef_da.properties | 19 ++- src/main/resources/l10n/JabRef_de.properties | 20 ++- src/main/resources/l10n/JabRef_en.properties | 18 +- src/main/resources/l10n/JabRef_es.properties | 20 ++- src/main/resources/l10n/JabRef_fa.properties | 18 +- src/main/resources/l10n/JabRef_fr.properties | 20 ++- src/main/resources/l10n/JabRef_in.properties | 18 +- src/main/resources/l10n/JabRef_it.properties | 18 +- src/main/resources/l10n/JabRef_ja.properties | 18 +- src/main/resources/l10n/JabRef_nl.properties | 18 +- src/main/resources/l10n/JabRef_no.properties | 18 +- .../resources/l10n/JabRef_pt_BR.properties | 20 ++- src/main/resources/l10n/JabRef_ru.properties | 20 ++- src/main/resources/l10n/JabRef_sv.properties | 20 ++- src/main/resources/l10n/JabRef_tr.properties | 20 ++- src/main/resources/l10n/JabRef_vi.properties | 20 ++- src/main/resources/l10n/JabRef_zh.properties | 20 ++- .../sf/jabref/logic/util/BuildInfoTest.java | 6 +- .../logic/util/version/VersionTest.java | 127 +++++++++++++++ 34 files changed, 956 insertions(+), 83 deletions(-) create mode 100644 src/main/java/net/sf/jabref/gui/actions/SearchForUpdateAction.java create mode 100644 src/main/java/net/sf/jabref/gui/help/NewVersionDialog.java create mode 100644 src/main/java/net/sf/jabref/gui/worker/VersionWorker.java create mode 100644 src/main/java/net/sf/jabref/logic/util/Version.java create mode 100644 src/main/java/net/sf/jabref/logic/util/VersionPreferences.java create mode 100644 src/test/java/net/sf/jabref/logic/util/version/VersionTest.java diff --git a/src/main/java/net/sf/jabref/JabRefGUI.java b/src/main/java/net/sf/jabref/JabRefGUI.java index b4e411e48440..d6c7759e2733 100644 --- a/src/main/java/net/sf/jabref/JabRefGUI.java +++ b/src/main/java/net/sf/jabref/JabRefGUI.java @@ -36,12 +36,15 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.ParserResultWarningDialog; import net.sf.jabref.gui.util.FocusRequester; +import net.sf.jabref.gui.worker.VersionWorker; import net.sf.jabref.importer.AutosaveStartupPrompter; import net.sf.jabref.importer.OpenDatabaseAction; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.preferences.LastFocusedTabPreferences; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.logic.util.Version; +import net.sf.jabref.logic.util.VersionPreferences; import net.sf.jabref.migrations.PreferencesMigrations; import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; @@ -65,6 +68,13 @@ public JabRefGUI(List loaded, boolean isBlank) { this.loaded = loaded; this.isBlank = isBlank; openWindow(); + JabRefGUI.checkForNewVersion(false); + } + + public static void checkForNewVersion(boolean manualExecution) { + Version toBeIgnored = new VersionPreferences(Globals.prefs).getIgnoredVersion(); + Version currentVersion = Globals.BUILD_INFO.getVersion(); + new VersionWorker(JabRefGUI.getMainFrame(), manualExecution, currentVersion, toBeIgnored).execute(); } private void openWindow() { diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index dda85b404977..8341a5b12087 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -70,6 +70,7 @@ import net.sf.jabref.logic.openoffice.StyleLoader; import net.sf.jabref.logic.remote.RemotePreferences; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.logic.util.VersionPreferences; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.CustomEntryType; @@ -419,7 +420,7 @@ public class JabRefPreferences { private static final String USER_HOME = System.getProperty("user.home"); /** - * Set with all custom {@link ImportFormat}s + * Set with all custom {@link net.sf.jabref.importer.fileformat.ImportFormat}s */ public final CustomImportList customImports; @@ -861,6 +862,9 @@ private JabRefPreferences() { defaults.put(MAX_BACK_HISTORY_SIZE, 10); defaults.put(LINE_LENGTH, 65); defaults.put(INDENT, 4); + + //versioncheck defaults + defaults.put(VersionPreferences.VERSION_IGNORED_UPDATE, ""); } public String getUser() { diff --git a/src/main/java/net/sf/jabref/cli/JabRefCLI.java b/src/main/java/net/sf/jabref/cli/JabRefCLI.java index f788f5261833..234b37a95f45 100644 --- a/src/main/java/net/sf/jabref/cli/JabRefCLI.java +++ b/src/main/java/net/sf/jabref/cli/JabRefCLI.java @@ -1,3 +1,18 @@ +/* Copyright (C) 2003-2016 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.cli; import net.sf.jabref.Globals; diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 8e79c51384cf..3dc1dac95ca0 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -92,6 +92,7 @@ import net.sf.jabref.gui.actions.NewDatabaseAction; import net.sf.jabref.gui.actions.NewEntryAction; import net.sf.jabref.gui.actions.NewSubDatabaseAction; +import net.sf.jabref.gui.actions.SearchForUpdateAction; import net.sf.jabref.gui.actions.SortTabsAction; import net.sf.jabref.gui.dbproperties.DatabasePropertiesDialog; import net.sf.jabref.gui.groups.EntryTableTransferHandler; @@ -715,7 +716,7 @@ public void about() { // General preferences dialog. The MacAdapter calls this method when "Preferences..." // is selected from the application menu. - public void preferences() { + public void showPreferencesDialog() { output(Localization.lang("Opening preferences...")); if (prefsDialog == null) { prefsDialog = new PreferencesDialog(JabRefFrame.this); @@ -1354,6 +1355,7 @@ private void fillMenu() { helpMenu.add(forkMeOnGitHubAction); helpMenu.add(donationAction); helpMenu.addSeparator(); + helpMenu.add(new SearchForUpdateAction()); helpMenu.add(about); mb.add(helpMenu); @@ -1476,6 +1478,9 @@ private void createToolBar() { tlb.add(donationAction); } + /** + * displays the String on the Status Line visible on the bottom of the JabRef mainframe + */ public void output(final String s) { SwingUtilities.invokeLater(() -> { statusLine.setText(s); @@ -1703,7 +1708,7 @@ public ShowPrefsAction() { @Override public void actionPerformed(ActionEvent e) { - preferences(); + showPreferencesDialog(); } } diff --git a/src/main/java/net/sf/jabref/gui/actions/SearchForUpdateAction.java b/src/main/java/net/sf/jabref/gui/actions/SearchForUpdateAction.java new file mode 100644 index 000000000000..83d30aa4392b --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/actions/SearchForUpdateAction.java @@ -0,0 +1,35 @@ +/* Copyright (C) 2016 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.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import net.sf.jabref.JabRefGUI; +import net.sf.jabref.logic.l10n.Localization; + +public class SearchForUpdateAction extends AbstractAction { + + public SearchForUpdateAction(){ + super(Localization.lang("Check for updates")); + } + + @Override + public void actionPerformed(ActionEvent e) { + JabRefGUI.checkForNewVersion(true); + } +} diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index 943db8b69dac..0c48eaf3f1e8 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -1,3 +1,18 @@ +/* Copyright (C) 2003-2016 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.desktop; import java.io.File; @@ -12,10 +27,12 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; +import net.sf.jabref.JabRefGUI; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypeEntryEditor; import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.external.UnknownExternalFileType; +import net.sf.jabref.gui.ClipBoardManager; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.FileListEntryEditor; import net.sf.jabref.gui.FileListTableModel; @@ -265,6 +282,27 @@ public static void openBrowser(String url) throws IOException { openExternalFilePlatformIndependent(fileType, url); } + /** + * Opens the url with the users standard Browser. + * If that fails a popup will be shown to instruct the user to open the link manually + * and the link gets copied to the clipboard + * @param url + */ + public static void openBrowserShowPopup(String url) { + try { + openBrowser(url); + } catch (IOException exception) { + new ClipBoardManager().setClipboardContents(url); + LOGGER.error("Could not open browser", exception); + String couldNotOpenBrowser = Localization.lang("Could not open browser."); + String openManually = Localization.lang("Please open %0 manually.", url); + String copiedToClipboard = Localization.lang("The_link_has_been_copied_to_the_clipboard."); + JabRefGUI.getMainFrame().output(couldNotOpenBrowser); + JOptionPane.showMessageDialog(JabRefGUI.getMainFrame(), couldNotOpenBrowser + "\n" + openManually +"\n"+ + copiedToClipboard, couldNotOpenBrowser, JOptionPane.ERROR_MESSAGE); + } + } + public static void openConsole(File file) throws IOException { if (file == null) { return; diff --git a/src/main/java/net/sf/jabref/gui/help/HelpAction.java b/src/main/java/net/sf/jabref/gui/help/HelpAction.java index ec550b094d02..83e10c2e3b73 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpAction.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpAction.java @@ -17,7 +17,6 @@ import java.awt.Dimension; import java.awt.event.ActionEvent; -import java.io.IOException; import javax.swing.Action; import javax.swing.Icon; @@ -25,7 +24,6 @@ import javax.swing.KeyStroke; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefGUI; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.actions.MnemonicAwareAction; @@ -83,12 +81,7 @@ public void setHelpFile(HelpFiles urlPart) { @Override public void actionPerformed(ActionEvent e) { - try { - JabRefDesktop.openBrowser("http://help.jabref.org/" + Globals.prefs.get(JabRefPreferences.LANGUAGE) + "/" - + helpPage.getPageName()); - } catch (IOException ex) { - LOGGER.warn("Could not open browser", ex); - JabRefGUI.getMainFrame().getCurrentBasePanel().output(Localization.lang("Could not open browser.")); - } + String url = "http://help.jabref.org/" + Globals.prefs.get(JabRefPreferences.LANGUAGE) + "/" + helpPage.getPageName(); + JabRefDesktop.openBrowserShowPopup(url); } } diff --git a/src/main/java/net/sf/jabref/gui/help/NewVersionDialog.java b/src/main/java/net/sf/jabref/gui/help/NewVersionDialog.java new file mode 100644 index 000000000000..61ee0511a1e4 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/help/NewVersionDialog.java @@ -0,0 +1,110 @@ +/* Copyright (C) 2016 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.help; + +import java.awt.Cursor; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.MouseEvent; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.event.MouseInputAdapter; + +import net.sf.jabref.Globals; +import net.sf.jabref.gui.desktop.JabRefDesktop; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.Version; +import net.sf.jabref.logic.util.VersionPreferences; + +public class NewVersionDialog extends JDialog { + + public NewVersionDialog(JFrame frame, Version currentVersion, Version latestVersion, Version toBeIgnored) { + super(frame); + setTitle(Localization.lang("New version available")); + + JLabel lblTitle = new JLabel(Localization.lang("A new version of JabRef has been released.")); + JLabel lblCurrentVersion = new JLabel(Localization.lang("Installed version") + ": " + currentVersion.getFullVersion()); + JLabel lblLatestVersion = new JLabel(Localization.lang("Latest version") + ": " + latestVersion.getFullVersion()); + + String localization = Localization.lang("To see what's new view the changelog."); + JLabel lblMoreInformation = new JLabel("" + localization + ""); + lblMoreInformation.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + lblMoreInformation.addMouseListener(new MouseInputAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + JabRefDesktop.openBrowserShowPopup(latestVersion.getChangelogUrl()); + } + }); + + JButton btnIgnoreUpdate = new JButton(Localization.lang("Ignore this update")); + btnIgnoreUpdate.addActionListener(e -> { + new VersionPreferences(Globals.prefs).setAsIgnoredVersion(toBeIgnored); + dispose(); + }); + + JButton btnDownloadUpdate = new JButton(Localization.lang("Download update")); + btnDownloadUpdate.addActionListener(e -> { + JabRefDesktop.openBrowserShowPopup(Version.JABREF_DOWNLOAD_URL); + dispose(); + }); + + JButton btnRemindMeLater = new JButton(Localization.lang("Remind me later")); + btnRemindMeLater.addActionListener(e -> dispose()); + + JPanel panel = new JPanel(); + panel.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.gridheight = 1; + c.fill = GridBagConstraints.BOTH; + c.insets = new Insets(2, 5, 5, 2); + + c.gridx = c.gridy = 0; + c.gridwidth = 3; + panel.add(lblTitle, c); + + c.gridy = 1; + panel.add(lblCurrentVersion, c); + + c.gridy = 2; + panel.add(lblLatestVersion, c); + + c.gridy = 3; + panel.add(lblMoreInformation, c); + + c.gridy = 4; + c.gridx = 0; + c.gridwidth = 1; + panel.add(btnDownloadUpdate, c); + + c.gridx = 1; + panel.add(btnIgnoreUpdate, c); + + c.gridx = 2; + panel.add(btnRemindMeLater, c); + + add(panel); + pack(); + setLocationRelativeTo(frame); + setModalityType(ModalityType.APPLICATION_MODAL); + setVisible(true); + } + +} diff --git a/src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java b/src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java index 8255089d1800..9727187acb2f 100644 --- a/src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java +++ b/src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java @@ -16,23 +16,16 @@ package net.sf.jabref.gui.menus.help; import java.awt.event.ActionEvent; -import java.io.IOException; import javax.swing.AbstractAction; import javax.swing.Action; -import net.sf.jabref.JabRefGUI; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.logic.l10n.Localization; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - public class DonateAction extends AbstractAction { - private static final Log LOGGER = LogFactory.getLog(DonateAction.class); - private static final String DONATION_LINK = "https://github.com/JabRef/jabref/wiki/Donations"; public DonateAction() { @@ -44,11 +37,6 @@ public DonateAction() { @Override public void actionPerformed(ActionEvent e) { - try { - JabRefDesktop.openBrowser(DONATION_LINK); - } catch (IOException ex) { - LOGGER.warn("Could not open browser", ex); - JabRefGUI.getMainFrame().getCurrentBasePanel().output(Localization.lang("Could not open browser.")); - } + JabRefDesktop.openBrowserShowPopup(DONATION_LINK); } } diff --git a/src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java b/src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java index 1b903792f9bd..b474cd948894 100644 --- a/src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java +++ b/src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java @@ -16,25 +16,17 @@ package net.sf.jabref.gui.menus.help; import java.awt.event.ActionEvent; -import java.io.IOException; import javax.swing.AbstractAction; import javax.swing.Action; -import net.sf.jabref.JabRefGUI; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.logic.l10n.Localization; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - @SuppressWarnings("serial") public class ForkMeOnGitHubAction extends AbstractAction { - private static final Log LOGGER = LogFactory.getLog(ForkMeOnGitHubAction.class); - - public ForkMeOnGitHubAction() { super(Localization.menuTitle("Fork me on GitHub"), IconTheme.JabRefIcon.GITHUB.getSmallIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Opens JabRef's GitHub page")); @@ -43,12 +35,6 @@ public ForkMeOnGitHubAction() { @Override public void actionPerformed(ActionEvent e) { - try { - JabRefDesktop.openBrowser("https://github.com/JabRef/jabref"); - } catch (IOException ex) { - LOGGER.warn("Could not open browser", ex); - JabRefGUI.getMainFrame().getCurrentBasePanel().output(Localization.lang("Could not open browser.") + " " - + Localization.lang("Please open http://github.com/JabRef/jabref manually.")); - } + JabRefDesktop.openBrowserShowPopup("https://github.com/JabRef/jabref"); } } diff --git a/src/main/java/net/sf/jabref/gui/worker/VersionWorker.java b/src/main/java/net/sf/jabref/gui/worker/VersionWorker.java new file mode 100644 index 000000000000..5b0c101084a3 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/worker/VersionWorker.java @@ -0,0 +1,101 @@ +/* Copyright (C) 2003-2016 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.worker; + +import java.io.IOException; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + +import javax.swing.JOptionPane; +import javax.swing.SwingWorker; + +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.help.NewVersionDialog; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.Version; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class VersionWorker extends SwingWorker { + + private static final Log LOGGER = LogFactory.getLog(VersionWorker.class); + + private final JabRefFrame mainFrame; + private final boolean manualExecution; + private final Version installedVersion; + private final Version toBeIgnored; + + public VersionWorker(JabRefFrame mainFrame, boolean manualExecution, Version installedVersion, Version toBeIgnored) { + this.mainFrame = Objects.requireNonNull(mainFrame); + this.manualExecution = manualExecution; + this.installedVersion = Objects.requireNonNull(installedVersion); + this.toBeIgnored = Objects.requireNonNull(toBeIgnored); + } + + @Override + protected Version doInBackground() throws Exception { + try { + return Version.getLatestVersion(); + } catch (IOException ioException) { + LOGGER.warn("Couldn't connect to the updateserver.", ioException); + return null; + } + } + + @Override + public void done(){ + if (this.isCancelled()){ + return; + } + + try { + Version latestVersion = this.get(); + + if (latestVersion == null){ + String couldNotConnect = Localization.lang("Couldn't connect to the update server."); + String tryLater = Localization.lang("Please try again later and/or check your network connection."); + if (manualExecution) { + JOptionPane.showMessageDialog(this.mainFrame, couldNotConnect + "\n" + tryLater, + couldNotConnect, JOptionPane.ERROR_MESSAGE); + } + this.mainFrame.output(couldNotConnect + " " + tryLater); + return; + } + + // only respect the ignored version on automated version checks + if (latestVersion.equals(toBeIgnored) && !manualExecution) { + return; + } + + boolean newer = latestVersion.isNewerThan(installedVersion); + if (newer){ + new NewVersionDialog(this.mainFrame, installedVersion, latestVersion, toBeIgnored); + return; + } + + String upToDate = Localization.lang("JabRef is up-to-date."); + if (manualExecution) { + JOptionPane.showMessageDialog(this.mainFrame, upToDate, upToDate, JOptionPane.INFORMATION_MESSAGE); + } + this.mainFrame.output(upToDate); + + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("Error while checking for updates", e); + } + } + +} diff --git a/src/main/java/net/sf/jabref/logic/util/BuildInfo.java b/src/main/java/net/sf/jabref/logic/util/BuildInfo.java index 058c6278b6f0..05fd18f21fde 100644 --- a/src/main/java/net/sf/jabref/logic/util/BuildInfo.java +++ b/src/main/java/net/sf/jabref/logic/util/BuildInfo.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2003-2015 JabRef contributors. +/* Copyright (C) 2003-2016 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 @@ -21,14 +21,14 @@ public class BuildInfo { - private static final String UNKOWN_VERSION = "*unknown*"; + public static final String UNKNOWN_VERSION = "*unknown*"; - public final static String OS = System.getProperty("os.name", UNKOWN_VERSION).toLowerCase(); - public final static String OS_VERSION = System.getProperty("os.version", UNKOWN_VERSION).toLowerCase(); - public final static String OS_ARCH = System.getProperty("os.arch", UNKOWN_VERSION).toLowerCase(); - public final static String JAVA_VERSION = System.getProperty("java.version", UNKOWN_VERSION).toLowerCase(); + public final static String OS = System.getProperty("os.name", UNKNOWN_VERSION).toLowerCase(); + public final static String OS_VERSION = System.getProperty("os.version", UNKNOWN_VERSION).toLowerCase(); + public final static String OS_ARCH = System.getProperty("os.arch", UNKNOWN_VERSION).toLowerCase(); + public final static String JAVA_VERSION = System.getProperty("java.version", UNKNOWN_VERSION).toLowerCase(); - private final String version; + private final Version version; private final String authors; private final String developers; private final String year; @@ -48,14 +48,14 @@ public BuildInfo(String path) { // nothing to do -> default already set } - version = properties.getProperty("version", UNKOWN_VERSION); + version = new Version(properties.getProperty("version", UNKNOWN_VERSION)); authors = properties.getProperty("authors", ""); year = properties.getProperty("year", ""); developers = properties.getProperty("developers", ""); } - public String getVersion() { + public Version getVersion() { return version; } diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java new file mode 100644 index 000000000000..7349c1f623c5 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -0,0 +1,154 @@ +/* Copyright (C) 2016 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.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.Objects; +import java.util.regex.Pattern; + +import org.json.JSONObject; + +/** + * Represents the Application Version with the major and minor number, the full Version String and if it's a developer version + */ +public class Version { + + public final static String JABREF_DOWNLOAD_URL = "http://www.fosshub.com/JabRef.html"; + private final static String JABREF_GITHUB_URL = "https://api.github.com/repos/JabRef/jabref/releases/latest"; + + private final String fullVersion; + private final int major; + private final int minor; + private final int patch; + private final boolean isDevelopmentVersion; + + + /** + * @param version must be in form of X.X (eg 3.3; 3.4dev) + */ + public Version(String version) { + if (version == null || "".equals(version) || version.equals(BuildInfo.UNKNOWN_VERSION)) { + this.fullVersion = BuildInfo.UNKNOWN_VERSION; + this.major = this.minor = this.patch = 0; + this.isDevelopmentVersion = false; + return; + } + + this.fullVersion = version; + isDevelopmentVersion = version.contains("dev"); + String[] versionParts = version.split("dev"); + String[] versionNumbers = versionParts[0].split(Pattern.quote(".")); + this.major = Integer.parseInt(versionNumbers[0]); + this.minor = versionNumbers.length >= 2 ? Integer.parseInt(versionNumbers[1]) : 0; + this.patch = versionNumbers.length >= 3 ? Integer.parseInt(versionNumbers[2]) : 0; + } + + /** + * Grabs the latest release version from the JabRef GitHub repository + * + * @return + * @throws IOException + */ + public static Version getLatestVersion() throws IOException { + URLConnection connection = new URL(JABREF_GITHUB_URL).openConnection(); + connection.setRequestProperty("Accept-Charset", "UTF-8"); + BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream())); + JSONObject obj = new JSONObject(rd.readLine()); + return new Version(obj.getString("tag_name").replaceFirst("v", "")); + } + + /** + * @return true if this version is newer than the passed one + */ + public boolean isNewerThan(Version otherVersion) { + Objects.requireNonNull(otherVersion); + if (Objects.equals(this, otherVersion)) { + return false; + } + if (this.getFullVersion().equals(BuildInfo.UNKNOWN_VERSION)) { + return false; + } + if (otherVersion.getFullVersion().equals(BuildInfo.UNKNOWN_VERSION)) { + return true; + } + + if (this.getMajor() > otherVersion.getMajor()) { + return true; + } + if (this.getMajor() == otherVersion.getMajor()) { + if (this.getMinor() > otherVersion.getMinor()) { + return true; + } + if (this.getMinor() == otherVersion.getMinor() && this.getPatch() > otherVersion.getPatch()) { + return true; + } + } + + return false; + } + + public String getFullVersion() { + return fullVersion; + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getPatch() { + return patch; + } + + public boolean isDevelopmentVersion() { + return isDevelopmentVersion; + } + + /** + * @return The link to the changelog on github to this specific version + * (https://github.com/JabRef/jabref/blob/vX.X/CHANGELOG.md) + */ + public String getChangelogUrl() { + String version = this.getMajor() + "." + this.getMinor() + (this.getPatch() != 0 ? "." + this.getPatch() : ""); + return "https://github.com/JabRef/jabref/blob/v" + version + "/CHANGELOG.md"; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof Version)) { + return false; + } + + Version otherVersion = (Version) other; + // till all the information are stripped from the fullverison this should suffice + return this.getFullVersion().equals(otherVersion.getFullVersion()); + } + + @Override + public String toString() { + return this.getFullVersion(); + } +} diff --git a/src/main/java/net/sf/jabref/logic/util/VersionPreferences.java b/src/main/java/net/sf/jabref/logic/util/VersionPreferences.java new file mode 100644 index 000000000000..e23d22ca4115 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/util/VersionPreferences.java @@ -0,0 +1,40 @@ +/* Copyright (C) 2016 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.util; + +import net.sf.jabref.JabRefPreferences; + + +public class VersionPreferences { + + public static final String VERSION_IGNORED_UPDATE = "versionIgnoreUpdate"; + + private final JabRefPreferences preferences; + + + public VersionPreferences(JabRefPreferences preferences) { + this.preferences = preferences; + } + + public void setAsIgnoredVersion(Version version) { + preferences.put(VERSION_IGNORED_UPDATE, version.toString()); + } + + public Version getIgnoredVersion() { + return new Version(preferences.get(VERSION_IGNORED_UPDATE)); + } + +} diff --git a/src/main/java/osx/macadapter/MacAdapter.java b/src/main/java/osx/macadapter/MacAdapter.java index 0d3b9f1a2ff8..798394547c6d 100644 --- a/src/main/java/osx/macadapter/MacAdapter.java +++ b/src/main/java/osx/macadapter/MacAdapter.java @@ -89,7 +89,7 @@ public void handlePreferences(PreferencesEvent arg0) { return; } - parentFrame.preferences(); + parentFrame.showPreferencesDialog(); } @Override diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 550158bcbb77..261de61d3a6c 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1320,8 +1320,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= -Please_open_http\://github.com/JabRef/jabref_manually.= - Rebind_C-f,_too= This_group_contains_all_entries._It_cannot_be_edited_or_removed.= @@ -1688,3 +1686,20 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index f04e9a7e8a14..cbd7d36fe5a5 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2028,7 +2028,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Look_ Could_not_open_browser.=Konnte_Browser_nicht_öffnen. Opens_JabRef's_GitHub_page=Öffnet_JabRefs_GitHub-Seite -Please_open_http\://github.com/JabRef/jabref_manually.=Bitte_öffnen_Sie_http\://github.com/JabRef/jabref_von_Hand. Rebind_C-f,_too=C-f_ebenfalls_neu_zuweisen This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Diese_Gruppe_enthält_alle_Einträge._Sie_kann_nicht_gelöscht_werden. @@ -2403,4 +2402,21 @@ Decryption_not_supported.=Entschlüsselung_wird_nicht_unterstützt. Cleared_'%0'_for_%1_entries='%0'_für_%1_Einträge_entfernt Set_'%0'_to_'%1'_for_%2_entries='%0'_für_%2_Einträge_auf_'%1'_gesetzt -Toggled_'%0'_for_%1_entries='%0'_für_%1_Einträge_geändert \ No newline at end of file +Toggled_'%0'_for_%1_entries='%0'_für_%1_Einträge_geändert + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index e887828d629d..66fbed6f8d33 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1935,7 +1935,8 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Unabl Opens_JabRef's_GitHub_page=Opens_JabRef's_GitHub_page Could_not_open_browser.=Could_not_open_browser. -Please_open_http\://github.com/JabRef/jabref_manually.=Please_open_http\://github.com/JabRef/jabref_manually. +Please_open_%0_manually.=Please_open_%0_manually. +The_link_has_been_copied_to_the_clipboard.=The_link_has_been_copied_to_the_clipboard. This_group_contains_all_entries._It_cannot_be_edited_or_removed.=This_group_contains_all_entries._It_cannot_be_edited_or_removed. @@ -2259,4 +2260,17 @@ Decryption_not_supported.=Decryption_not_supported. Cleared_'%0'_for_%1_entries=Cleared_'%0'_for_%1_entries Set_'%0'_to_'%1'_for_%2_entries=Set_'%0'_to_'%1'_for_%2_entries -Toggled_'%0'_for_%1_entries=Toggled_'%0'_for_%1_entries \ No newline at end of file +Toggled_'%0'_for_%1_entries=Toggled_'%0'_for_%1_entries + +Check_for_updates=Check_for_updates +Download_update=Download_update +New_version_available=New_version_available +Installed_version=Installed_version +Remind_me_later=Remind_me_later +Ignore_this_update=Ignore_this_update +Couldn't_connect_to_the_update_server.=Couldn't_connect_to_the_update_server. +Please_try_again_later_and/or_check_your_network_connection.=Please_try_again_later_and/or_check_your_network_connection. +To_see_what's_new_view_the_changelog.=To_see_what's_new_view_the_changelog. +A_new_version_of_JabRef_has_been_released.=A_new_version_of_JabRef_has_been_released. +JabRef_is_up-to-date.=JabRef_is_up-to-date. +Latest_version=Latest_version diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 2fb5b39ecb60..d68b3cadd23f 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1221,7 +1221,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=No_se Could_not_open_browser.=No_se_puede_abrir_el_explorador. Opens_JabRef's_GitHub_page=Abrir_la_página_de_JabRef_en_GitHub -Please_open_http\://github.com/JabRef/jabref_manually.=Por_favor,_abra_http\://github.com/JabRef/jabref_manualmente Rebind_C-f,_too=Recombinar_C-f,_también This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Este_grupo_contiene_todas_las_entradas._No_puede_ser_eliminado_o_editado. @@ -1588,4 +1587,21 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries=Ajustes_de_'%0'_para_%1_entradas Set_'%0'_to_'%1'_for_%2_entries=Establecer_'%0'_a_'%1'_para_%2_entradas -Toggled_'%0'_for_%1_entries=Cambiada_'%0'_para_%1_entradas \ No newline at end of file +Toggled_'%0'_for_%1_entries=Cambiada_'%0'_para_%1_entradas + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index b2bbeafdef4f..ea5d7e69556e 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1984,7 +1984,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= Opens_JabRef's_GitHub_page= Could_not_open_browser.= -Please_open_http\://github.com/JabRef/jabref_manually.= This_group_contains_all_entries._It_cannot_be_edited_or_removed.= @@ -2375,3 +2374,20 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 56fc60bc4e71..844be8865692 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1261,7 +1261,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Impos Could_not_open_browser.=Le_navigateur_n'a_pas_pu_être_lancé. Opens_JabRef's_GitHub_page=Ouvre_la_page_GitHub_de_JabRef -Please_open_http\://github.com/JabRef/jabref_manually.=Ouvrez_http\://github.com/JabRef/jabref_manuellement,_SVP. Rebind_C-f,_too=Ré-associer_aussi_C-f This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Ce_groupe_contient_toutes_les_entrées._Il_ne_peut_pas_être_modifié_ou_supprimé. @@ -1632,4 +1631,21 @@ Decryption_not_supported.=Déchiffrement_non_supporté. Cleared_'%0'_for_%1_entries=Réinitialisés_'%0'_pour_%1_entrées Set_'%0'_to_'%1'_for_%2_entries='%0'_mis_à_'%1'_pour_%2_entrées -Toggled_'%0'_for_%1_entries='%0'_modifiée_pour_%1_entrées \ No newline at end of file +Toggled_'%0'_for_%1_entries='%0'_modifiée_pour_%1_entrées + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 89b0904f65ca..60d981a62328 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1238,7 +1238,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Penam Could_not_open_browser.=Penjelajah_tidak_bisa_dibuka. Opens_JabRef's_GitHub_page=Buka_halaman_JabRef_di_GitHub -Please_open_http\://github.com/JabRef/jabref_manually.=Buka_http\://github.com/JabRef/jabref_secara_manual. Rebind_C-f,_too= This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Grup_ini_mengandung_semua_entri._Tidak_bisa_disunting_atau_dihapus. @@ -1608,3 +1607,20 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 8c33ecf77b97..0e320e3c78ac 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1338,7 +1338,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Impos Could_not_open_browser.=Impossibile_avviare_il_browser Opens_JabRef's_GitHub_page=Apri_la_pagina_di_JabRef_su_GitHub -Please_open_http\://github.com/JabRef/jabref_manually.=Aprire_manualmente_la_pagina_http\://github.com/JabRef/jabref Rebind_C-f,_too=Riassociare_anche_C-f This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Questo_gruppo_contiene_tutte_le_voci._Non_pu\u00f2_essere_modificato_o_rimosso. @@ -1708,3 +1707,20 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries=Reinizializzati_'%0'_per_%1_voce/i Set_'%0'_to_'%1'_for_%2_entries='%0'_impostata_a_'%1'_per_%2_voce/i Toggled_'%0'_for_%1_entries=Modificata_la_valutazione_di_'%0'_per_%1_voce/i + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index d7ad6051f83b..8b28b96171a2 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2009,7 +2009,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=要 Could_not_open_browser.=ブラウザを開くことができませんでした。 Opens_JabRef's_GitHub_page=JabRefのGitHubページを開きます -Please_open_http\://github.com/JabRef/jabref_manually.=手動でhttp\://github.com/JabRef/jabrefを開いてください。 Rebind_C-f,_too=C-fもバインドし直します This_group_contains_all_entries._It_cannot_be_edited_or_removed.=このグループは全項目を含んでいます。編集したり削除したりすることはできません。 @@ -2353,3 +2352,20 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 4a818cc7ac42..0fef6105649f 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2011,7 +2011,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= -Please_open_http\://github.com/JabRef/jabref_manually.= Rebind_C-f,_too= This_group_contains_all_entries._It_cannot_be_edited_or_removed.= @@ -2384,3 +2383,20 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 3712929711f5..9606110dfbc5 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2406,7 +2406,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= -Please_open_http\://github.com/JabRef/jabref_manually.= Rebind_C-f,_too= This_group_contains_all_entries._It_cannot_be_edited_or_removed.= @@ -2780,3 +2779,20 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 82e792164288..8538273175e6 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1235,7 +1235,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Não_ Could_not_open_browser.=Não_foi_possível_abrir_o_navegador. Opens_JabRef's_GitHub_page=Abrir_a_página_do_JabRef_no_GitHub -Please_open_http\://github.com/JabRef/jabref_manually.= Rebind_C-f,_too=Recombinar_C-f_também This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Este_grupo_tem_todas_as_entradas._Ele_não_pode_ser_editado_ou_removido. @@ -1601,4 +1600,21 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries=Definir_'%0'_'%1'_para_%2_registros -Toggled_'%0'_for_%1_entries= \ No newline at end of file +Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index d6c1882ba351..66bc9b7514e0 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1983,7 +1983,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Не_ Opens_JabRef's_GitHub_page=Открывает_страницу_JabRef_на_GitHub Could_not_open_browser.=Не_удалось_открыть_браузер. -Please_open_http\://github.com/JabRef/jabref_manually.=Откройте_ссылку_http\://github.com/JabRef/jabref_вручную. This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Эта_группа_содержит_все_записи._Ее_удаление_или_изменение_невозможно. @@ -2351,4 +2350,21 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries=Установить_'%0'_'%1'_для_%2_записей -Toggled_'%0'_for_%1_entries=Изменение_'%0'_для_%1_записей \ No newline at end of file +Toggled_'%0'_for_%1_entries=Изменение_'%0'_для_%1_записей + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 4cf43a4a5977..687ffd85d7da 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -854,7 +854,6 @@ Please_enter_the_desired_name\:=Ange_det_önskade_namnet\: Please_enter_the_field_to_search_(e.g._keywords)_and_the_keyword_to_search_it_for_(e.g._electrical).= Please_enter_the_string's_label=Ange_namnet_på_strängen Please_move_the_file_manually_and_link_in_place.= -Please_open_http\://github.com/JabRef/jabref_manually.= Please_open_or_start_a_new_database_before_searching= Please_select_an_importer.= Please_select_exactly_one_group_to_move.=Välj_exakt_en_grupp_att_flytta. @@ -1542,8 +1541,23 @@ Get_fulltext= Download_from_URL=Ladda_ned_från_URL Decryption_not_supported.=Avkryptering_stöds_ej. - - Cleared_'%0'_for_%1_entries=Rensade_'%0'_för_%1_poster Set_'%0'_to_'%1'_for_%2_entries= Toggled_'%0'_for_%1_entries=Växlade_'%0'_för_%1_poster + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 78a52270d3a1..fed34c818887 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1255,7 +1255,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Arzu_ Could_not_open_browser.=Tarayıcı_açılamadı. Opens_JabRef's_GitHub_page=JabRef'in_GitHub_sayfasını_açar -Please_open_http\://github.com/JabRef/jabref_manually.=Lütfen_http\://github.com/JabRef/jabref'i_manüel_olarak_açın. Rebind_C-f,_too=C-f'yi_de_tekrar_bağla This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Bu_grup_tüm_girdileri_içeriyor._Düzenlenemez_ya_da_silinemez. @@ -1620,4 +1619,21 @@ Decryption_not_supported.=Şifre_çözme_desteklenmiyor. Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries=%2_girdiler_için_'%0'_'%1'a_ata -Toggled_'%0'_for_%1_entries=%1_girdiler_için_'%0'_değiştirildi \ No newline at end of file +Toggled_'%0'_for_%1_entries=%1_girdiler_için_'%0'_değiştirildi + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 1f2e8f06f4e3..a41d1408c3a1 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2005,7 +2005,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= -Please_open_http\://github.com/JabRef/jabref_manually.= Rebind_C-f,_too= This_group_contains_all_entries._It_cannot_be_edited_or_removed.= @@ -2375,4 +2374,21 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= -Toggled_'%0'_for_%1_entries= \ No newline at end of file +Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 233dd13cb299..f258102b62c1 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1312,7 +1312,6 @@ Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=无 Could_not_open_browser.=无法打开浏览器。 Opens_JabRef's_GitHub_page=打开_JabRef_在_GitHub_上的页面 -Please_open_http\://github.com/JabRef/jabref_manually.=请手动打开_http\://github.com/JabRef/jabref Rebind_C-f,_too= This_group_contains_all_entries._It_cannot_be_edited_or_removed.=这个组包含所有记录,不可以被编辑或移除。 @@ -1614,4 +1613,21 @@ Decryption_not_supported.= Cleared_'%0'_for_%1_entries= Set_'%0'_to_'%1'_for_%2_entries= -Toggled_'%0'_for_%1_entries= \ No newline at end of file +Toggled_'%0'_for_%1_entries= + +Check_for_updates= +Download_update= +New_version_available= +Installed_version= +Remind_me_later= +Ignore_this_update= +Couldn't_connect_to_the_update_server.= +Please_try_again_later_and/or_check_your_network_connection.= +To_see_what's_new_view_the_changelog.= +A_new_version_of_JabRef_has_been_released.= +JabRef_is_up-to-date.= +Latest_version= + +Please_open_%0_manually.= + +The_link_has_been_copied_to_the_clipboard.= diff --git a/src/test/java/net/sf/jabref/logic/util/BuildInfoTest.java b/src/test/java/net/sf/jabref/logic/util/BuildInfoTest.java index 8c3b941676b5..a80df9d6d499 100644 --- a/src/test/java/net/sf/jabref/logic/util/BuildInfoTest.java +++ b/src/test/java/net/sf/jabref/logic/util/BuildInfoTest.java @@ -9,13 +9,13 @@ public class BuildInfoTest { @Test public void testDefaults() { BuildInfo buildInfo = new BuildInfo("asdf"); - assertEquals("*unknown*", buildInfo.getVersion()); + assertEquals("*unknown*", buildInfo.getVersion().getFullVersion()); } @Test public void testFileImport() { BuildInfo buildInfo = new BuildInfo("/net/sf/jabref/util/build.properties"); - assertEquals("42", buildInfo.getVersion()); + assertEquals("42", buildInfo.getVersion().getFullVersion()); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java new file mode 100644 index 000000000000..808c7429e6bb --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java @@ -0,0 +1,127 @@ +package net.sf.jabref.logic.util.version; + + +import net.sf.jabref.logic.util.BuildInfo; +import net.sf.jabref.logic.util.Version; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class VersionTest { + + @Test + public void unknownVersion() { + Version version = new Version(BuildInfo.UNKNOWN_VERSION); + assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); + } + + @Test + public void versionOneDigit() { + String versionText = "1"; + Version version = new Version(versionText); + assertEquals(versionText, version.getFullVersion()); + assertEquals(1, version.getMajor()); + assertEquals(0, version.getMinor()); + assertEquals(0, version.getPatch()); + assertFalse(version.isDevelopmentVersion()); + } + + @Test + public void versionTwoDigits() { + String versionText = "1.2"; + Version version = new Version(versionText); + assertEquals(versionText, version.getFullVersion()); + assertEquals(1, version.getMajor()); + assertEquals(2, version.getMinor()); + assertEquals(0, version.getPatch()); + assertFalse(version.isDevelopmentVersion()); + } + + @Test + public void versionThreeDigits() { + String versionText = "1.2.3"; + Version version = new Version(versionText); + assertEquals(versionText, version.getFullVersion()); + assertEquals(1, version.getMajor()); + assertEquals(2, version.getMinor()); + assertEquals(3, version.getPatch()); + assertFalse(version.isDevelopmentVersion()); + } + + @Test + public void versionOneDigitDevVersion() { + String versionText = "1dev"; + Version version = new Version(versionText); + assertEquals(versionText, version.getFullVersion()); + assertEquals(1, version.getMajor()); + assertEquals(0, version.getMinor()); + assertEquals(0, version.getPatch()); + assertTrue(version.isDevelopmentVersion()); + } + + @Test + public void versionTwoDigitDevVersion() { + String versionText = "1.2dev"; + Version version = new Version(versionText); + assertEquals(versionText, version.getFullVersion()); + assertEquals(1, version.getMajor()); + assertEquals(2, version.getMinor()); + assertEquals(0, version.getPatch()); + assertTrue(version.isDevelopmentVersion()); + } + + @Test + public void versionThreeDigitDevVersion() { + String versionText = "1.2.3dev"; + Version version = new Version(versionText); + assertEquals(versionText, version.getFullVersion()); + assertEquals(1, version.getMajor()); + assertEquals(2, version.getMinor()); + assertEquals(3, version.getPatch()); + assertTrue(version.isDevelopmentVersion()); + } + + @Test + public void versionNewerThan() { + Version olderVersion = new Version("2.4"); + Version newerVersion = new Version("4.2"); + assertTrue(newerVersion.isNewerThan(olderVersion)); + } + + @Test + public void versionNewerThanDevTwoDigits() { + Version older = new Version("4.2"); + Version newer = new Version("4.3dev"); + assertTrue(newer.isNewerThan(older)); + } + + @Test + public void versionNewerThanDevThreeDigits() { + Version older = new Version("4.2.1"); + Version newer = new Version("4.3dev"); + assertTrue(newer.isNewerThan(older)); + } + + @Test + public void versionNewerPatch() { + Version older = new Version("4.2.1"); + Version newer = new Version("4.2.2"); + assertTrue(newer.isNewerThan(older)); + } + + @Test + public void changelogWithTwoDigits(){ + Version version = new Version("3.4"); + assertEquals("https://github.com/JabRef/jabref/blob/v3.4/CHANGELOG.md", version.getChangelogUrl()); + } + + @Test + public void changelogWithThreeDigits(){ + Version version = new Version("3.4.1"); + assertEquals("https://github.com/JabRef/jabref/blob/v3.4.1/CHANGELOG.md", version.getChangelogUrl()); + } + +} From 9a38dcd11714b80a8a45db1acdf23b95c016e190 Mon Sep 17 00:00:00 2001 From: Matthias Geiger Date: Tue, 28 Jun 2016 14:22:04 +0200 Subject: [PATCH 161/268] Changelog documentation for #1459 implementing #661 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26d697e4a949..f7ec24425971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed -- [#1485](https://github.com/JabRef/jabref/issues/1485) Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography +- Implemented [#661](https://github.com/JabRef/jabref/issues/661): Introducing a "check for updates" mechnism (manually/automatic at startup) +- [#1485](https://github.com/JabRef/jabref/issues/1485): Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography - [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view ### Fixed From a24b5444ddc640c077f14e95be8de537dfc6b662 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 28 Jun 2016 15:24:21 +0200 Subject: [PATCH 162/268] Improve group performance (#1520) * Lazy init JournalAbbreviationRepository * Fix tests * Add test for bibentry and mark getField as deprecated * Performance improvements for groups * Ignore failing test --- .../net/sf/jabref/benchmarks/Benchmarks.java | 16 +++++ src/main/java/net/sf/jabref/JabRefMain.java | 2 +- .../net/sf/jabref/exporter/ExportFormat.java | 8 +-- .../jabref/external/DownloadExternalFile.java | 4 +- .../jabref/external/DroppedFileHandler.java | 2 +- .../sf/jabref/external/MoveFileAction.java | 2 +- .../java/net/sf/jabref/gui/BasePanel.java | 13 ++-- .../java/net/sf/jabref/gui/PreviewPanel.java | 3 +- .../sf/jabref/gui/actions/CleanupAction.java | 3 +- .../sf/jabref/gui/groups/GroupSelector.java | 1 - .../gui/groups/GroupTreeCellRenderer.java | 9 ++- .../gui/groups/GroupTreeNodeViewModel.java | 5 +- .../gui/journals/ManageJournalsPanel.java | 9 +-- .../gui/openoffice/OpenOfficePanel.java | 3 +- .../autocompleter/AutoCompleterFactory.java | 8 ++- .../autocompleter/ContentAutoCompleters.java | 24 +------ .../autocompleter/JournalAutoCompleter.java | 48 ++++++++++++++ .../jabref/logic/cleanup/CleanupWorker.java | 10 +-- .../logic/cleanup/RenamePdfCleanup.java | 10 +-- .../sf/jabref/logic/groups/KeywordGroup.java | 2 +- .../journals/JournalAbbreviationLoader.java | 8 +-- .../net/sf/jabref/logic/layout/Layout.java | 8 +-- .../sf/jabref/logic/layout/LayoutEntry.java | 18 +++--- .../sf/jabref/logic/layout/LayoutHelper.java | 10 +-- .../layout/format/JournalAbbreviator.java | 10 +-- .../jabref/logic/openoffice/OOBibStyle.java | 14 ++--- .../jabref/logic/openoffice/StyleLoader.java | 14 ++--- .../net/sf/jabref/logic/util/io/FileUtil.java | 9 +-- .../net/sf/jabref/model/entry/BibEntry.java | 1 + .../sf/jabref/exporter/ExportFormatTest.java | 2 +- .../jabref/exporter/HtmlExportFormatTest.java | 2 +- .../AutoCompleterFactoryTest.java | 31 +++++----- .../logic/cleanup/CleanupWorkerTest.java | 3 +- .../logic/cleanup/RenamePdfCleanupTest.java | 10 +-- .../logic/journals/AbbreviationsTest.java | 26 ++++---- .../jabref/logic/layout/LayoutEntryTest.java | 4 +- .../sf/jabref/logic/layout/LayoutTest.java | 4 +- .../logic/openoffice/OOBibStyleTest.java | 62 ++++++++++--------- .../logic/openoffice/StyleLoaderTest.java | 31 +++++----- .../sf/jabref/logic/util/io/FileUtilTest.java | 7 +-- .../sf/jabref/model/entry/BibEntryTest.java | 12 +++- 41 files changed, 257 insertions(+), 211 deletions(-) create mode 100644 src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index 3c91bfea5548..e041f7217799 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -17,7 +17,10 @@ import net.sf.jabref.exporter.SavePreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; +import net.sf.jabref.logic.groups.GroupHierarchyType; +import net.sf.jabref.logic.groups.KeywordGroup; import net.sf.jabref.logic.layout.format.HTMLChars; import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; import net.sf.jabref.logic.search.SearchQuery; @@ -52,6 +55,7 @@ public void init() throws IOException { entry.setField("title", "This is my title " + i); entry.setField("author", "Firstname Lastname and FirstnameA LastnameA and FirstnameB LastnameB" + i); entry.setField("journal", "Journal Title " + i); + entry.setField("keyword", "testkeyword"); entry.setField("year", "1" + i); entry.setField("rnd", "2" + randomizer.nextInt()); database.insertEntry(entry); @@ -119,6 +123,18 @@ public String htmlToLatexConversion() { return f.format(htmlConversionString); } + @Benchmark + public boolean keywordGroupContains() throws ParseException { + KeywordGroup group = new KeywordGroup("testGroup", "keyword", "testkeyword", false, false, + GroupHierarchyType.INDEPENDENT); + return group.containsAll(database.getEntries()); + } + + @Benchmark + public boolean keywordGroupContainsWord() throws ParseException { + return KeywordGroup.containsWord("testWord", "Some longer test string containing testWord the test word"); + } + public static void main(String[] args) throws IOException, RunnerException { Main.main(args); } diff --git a/src/main/java/net/sf/jabref/JabRefMain.java b/src/main/java/net/sf/jabref/JabRefMain.java index 1754bc8b9451..93a4420e7e3a 100644 --- a/src/main/java/net/sf/jabref/JabRefMain.java +++ b/src/main/java/net/sf/jabref/JabRefMain.java @@ -68,7 +68,7 @@ private static void start(String[] args) { ExportFormats.initAllExports(); // Read list(s) of journal names and abbreviations - Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(Globals.prefs); + Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(); // Check for running JabRef RemotePreferences remotePreferences = new RemotePreferences(Globals.prefs); diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormat.java b/src/main/java/net/sf/jabref/exporter/ExportFormat.java index 642cc70fc249..b4d12d013e57 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/ExportFormat.java @@ -213,7 +213,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String // Print header try (Reader reader = getReader(lfFileName + ".begin.layout")) { - LayoutHelper layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader.getRepository()); + LayoutHelper layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); beginLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was cast, export filter doesn't have a begin @@ -239,7 +239,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String Layout defLayout; LayoutHelper layoutHelper; try (Reader reader = getReader(lfFileName + ".layout")) { - layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader.getRepository()); + layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); defLayout = layoutHelper.getLayoutFromText(); } if (defLayout != null) { @@ -261,7 +261,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String } else { try (Reader reader = getReader(lfFileName + '.' + type + ".layout")) { // We try to get a type-specific layout for this entry. - layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader.getRepository()); + layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); layout = layoutHelper.getLayoutFromText(); layouts.put(type, layout); if (layout != null) { @@ -285,7 +285,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String // changed section - begin (arudert) Layout endLayout = null; try (Reader reader = getReader(lfFileName + ".end.layout")) { - layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader.getRepository()); + layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); endLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was thrown, export filter doesn't have an end diff --git a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java index c0d0e6b0782d..12cc76d7ee47 100644 --- a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java +++ b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java @@ -266,9 +266,11 @@ private void downloadFinished() { editor.setOkEnabled(true); editor.getProgressBar().setValue(editor.getProgressBar().getMaximum()); } + // FIXME: will break download if no bibtexkey is present! private String getSuggestedFileName(String suffix) { - String plannedName = FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), frame.getCurrentBasePanel().getSelectedEntries().get(0), Globals.journalAbbreviationLoader.getRepository()); + String plannedName = FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), + frame.getCurrentBasePanel().getSelectedEntries().get(0), Globals.journalAbbreviationLoader); if (!suffix.isEmpty()) { plannedName += "." + suffix; diff --git a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java index c5232f56a50c..83c166f7caf4 100644 --- a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java +++ b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java @@ -350,7 +350,7 @@ private boolean showLinkMoveCopyRenameDialog(String linkFileName, ExternalFileTy renameCheckBox.setText(Localization.lang("Rename file to").concat(": ")); // Determine which name to suggest: - String targetName = FileUtil.createFileNameFromPattern(database, entry, Globals.journalAbbreviationLoader.getRepository()); + String targetName = FileUtil.createFileNameFromPattern(database, entry, Globals.journalAbbreviationLoader); renameToTextBox.setText(targetName.concat(".").concat(fileType.getExtension())); diff --git a/src/main/java/net/sf/jabref/external/MoveFileAction.java b/src/main/java/net/sf/jabref/external/MoveFileAction.java index 9533006abf33..4167851531f8 100644 --- a/src/main/java/net/sf/jabref/external/MoveFileAction.java +++ b/src/main/java/net/sf/jabref/external/MoveFileAction.java @@ -112,7 +112,7 @@ public void actionPerformed(ActionEvent event) { // Determine which name to suggest: String suggName = FileUtil .createFileNameFromPattern(eEditor.getDatabase(), eEditor.getEntry(), - Globals.journalAbbreviationLoader.getRepository()) + Globals.journalAbbreviationLoader) .concat(entry.type.isPresent() ? "." + entry.type.get().getExtension() : ""); CheckBoxMessage cbm = new CheckBoxMessage(Localization.lang("Move file to file directory?"), Localization.lang("Rename to '%0'", suggName), diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 9a32b0ebc332..711ee6799b9e 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -990,8 +990,7 @@ private void copyKeyAndTitle() { "\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); Layout layout; try { - layout = new LayoutHelper(sr, Globals.journalAbbreviationLoader.getRepository()) - .getLayoutFromText(); + layout = new LayoutHelper(sr, Globals.journalAbbreviationLoader).getLayoutFromText(); } catch (IOException e) { LOGGER.info("Could not get layout", e); return; @@ -1321,11 +1320,6 @@ public void run() { JabRefExecutorService.INSTANCE.submit(timerTask, 200); } } - - @Subscribe - public void listen(EntryChangedEvent entryChangedEvent) { - scheduleUpdate(); - } } /** @@ -1583,7 +1577,7 @@ public void setupMainPanel() { this.getDatabase().registerListener(new AutoCompleteListener()); } else { // create empty ContentAutoCompleters() if autoCompletion is deactivated - autoCompleters = new ContentAutoCompleters(Globals.journalAbbreviationLoader); + autoCompleters = new ContentAutoCompleters(); } // restore floating search result @@ -1603,7 +1597,8 @@ public void updateSearchManager() { private void instantiateSearchAutoCompleter() { AutoCompletePreferences autoCompletePreferences = new AutoCompletePreferences(Globals.prefs); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(autoCompletePreferences); + AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(autoCompletePreferences, + Globals.journalAbbreviationLoader); searchAutoCompleter = autoCompleterFactory.getPersonAutoCompleter(); for (BibEntry entry : database.getEntries()) { searchAutoCompleter.addBibtexEntry(entry); diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index 25490721b205..0868f26f648f 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -261,8 +261,7 @@ public void updateLayout(String layoutFormat) { private void updateLayout() { StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); try { - layout = Optional - .of(new LayoutHelper(sr, Globals.journalAbbreviationLoader.getRepository()).getLayoutFromText()); + layout = Optional.of(new LayoutHelper(sr, Globals.journalAbbreviationLoader).getLayoutFromText()); } catch (IOException e) { layout = Optional.empty(); LOGGER.debug("no layout could be set", e); diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java index b6087fe40d01..fae0ac0aba1b 100644 --- a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java @@ -161,8 +161,7 @@ private int showDialog(CleanupPresetPanel presetPanel) { private void doCleanup(CleanupPreset preset, BibEntry entry, NamedCompound ce) { // Create and run cleaner BibDatabaseContext bibDatabaseContext = panel.getBibDatabaseContext(); - CleanupWorker cleaner = new CleanupWorker(bibDatabaseContext, - Globals.journalAbbreviationLoader.getRepository()); + CleanupWorker cleaner = new CleanupWorker(bibDatabaseContext, Globals.journalAbbreviationLoader); List changes = cleaner.cleanup(preset, entry); unsuccessfulRenames = cleaner.getUnsuccessfulRenames(); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index bb5cd591e6b3..e9320e219f15 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -685,7 +685,6 @@ public void revalidateGroups(TreePath[] selectionPaths, Enumeration ex */ private void revalidateGroups(TreePath[] selectionPaths, Enumeration expandedNodes, GroupTreeNodeViewModel node) { - groupsTreeModel.reload(); groupsTree.clearSelection(); if (selectionPaths != null) { groupsTree.setSelectionPaths(selectionPaths); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java index 23be5c0fb93e..9164283d82c8 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeCellRenderer.java @@ -25,6 +25,7 @@ import javax.swing.Icon; import javax.swing.JLabel; import javax.swing.JTree; +import javax.swing.border.Border; import javax.swing.tree.DefaultTreeCellRenderer; import net.sf.jabref.logic.groups.GroupTreeNode; @@ -62,10 +63,14 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean GroupTreeNodeViewModel viewModel = (GroupTreeNodeViewModel) value; JLabel label = (JLabel) c; + Border border; if (Objects.equals(highlightBorderCell, value)) { - label.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + border = BorderFactory.createLineBorder(Color.BLACK); } else { - label.setBorder(BorderFactory.createEmptyBorder()); + border = BorderFactory.createEmptyBorder(); + } + if (label.getBorder() != border) { + label.setBorder(border); } Boolean red = printInRed(viewModel) && !selected; // do not print currently selected node in red diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java index 417fb12fdfd2..8c0c91e4cc00 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -43,12 +43,10 @@ import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.groups.MoveGroupChange; -import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; public class GroupTreeNodeViewModel implements Transferable, TreeNode { - private static final int MAX_DISPLAYED_LETTERS = 35; private static final Icon GROUP_REFINING_ICON = IconTheme.JabRefIcon.GROUP_REFINING.getSmallIcon(); private static final Icon GROUP_INCLUDING_ICON = IconTheme.JabRefIcon.GROUP_INCLUDING.getSmallIcon(); private static final Icon GROUP_REGULAR_ICON = null; @@ -189,9 +187,8 @@ protected boolean printInItalics() { public String getText() { AbstractGroup group = node.getGroup(); - String name = StringUtil.limitStringLength(group.getName(), MAX_DISPLAYED_LETTERS); StringBuilder sb = new StringBuilder(60); - sb.append(name); + sb.append(group.getName()); if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS) && JabRefGUI.getMainFrame() != null) { diff --git a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java index cdcea17c256a..110b6c60bd83 100644 --- a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java +++ b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java @@ -58,7 +58,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; @@ -392,12 +391,8 @@ private void storeSettings() { } Globals.prefs.putStringList(JabRefPreferences.EXTERNAL_JOURNAL_LISTS, extFiles); - // Update the autocompleter for the "journal" field in all base panels, - // so added journal names are available: - for (BasePanel basePanel : frame.getBasePanelList()) { - basePanel.getAutoCompleters().addJournalListToAutoCompleter(); - } - + // Update journal abbreviation loader + Globals.journalAbbreviationLoader.update(Globals.prefs); } diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java index 56dbbcc1b5a5..73d43b363cf9 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java @@ -126,8 +126,7 @@ private OpenOfficePanel() { update = new JButton(IconTheme.JabRefIcon.REFRESH.getSmallIcon()); update.setToolTipText(Localization.lang("Sync OpenOffice/LibreOffice bibliography")); preferences = new OpenOfficePreferences(Globals.prefs); - loader = new StyleLoader(preferences, Globals.journalAbbreviationLoader.getRepository(), - Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(preferences, Globals.journalAbbreviationLoader, Globals.prefs.getDefaultEncoding()); } public static OpenOfficePanel getInstance() { diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java index 11adb88f8465..9e9f4f7d2c4f 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java @@ -18,6 +18,7 @@ import java.util.Arrays; import java.util.Objects; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -29,10 +30,11 @@ public class AutoCompleterFactory { private final AutoCompletePreferences preferences; + private final JournalAbbreviationLoader abbreviationLoader; - - public AutoCompleterFactory(AutoCompletePreferences preferences) { + public AutoCompleterFactory(AutoCompletePreferences preferences, JournalAbbreviationLoader abbreviationLoader) { this.preferences = Objects.requireNonNull(preferences); + this.abbreviationLoader = Objects.requireNonNull(abbreviationLoader); } public AutoCompleter getFor(String fieldName) { @@ -43,7 +45,7 @@ public AutoCompleter getFor(String fieldName) { } else if ("crossref".equals(fieldName)) { return new BibtexKeyAutoCompleter(preferences); } else if ("journal".equals(fieldName) || "publisher".equals(fieldName)) { - return new EntireFieldAutoCompleter(fieldName, preferences); + return new JournalAutoCompleter(fieldName, preferences, abbreviationLoader); } else { return new DefaultAutoCompleter(fieldName, preferences); } diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/ContentAutoCompleters.java b/src/main/java/net/sf/jabref/logic/autocompleter/ContentAutoCompleters.java index f319f9fe9482..2951af38ae97 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/ContentAutoCompleters.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/ContentAutoCompleters.java @@ -5,25 +5,19 @@ import java.util.Objects; import net.sf.jabref.MetaData; -import net.sf.jabref.logic.journals.Abbreviation; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.database.BibDatabase; public class ContentAutoCompleters extends AutoCompleters { - private final JournalAbbreviationLoader abbreviationLoader; - - - public ContentAutoCompleters(JournalAbbreviationLoader abbreviationLoader) { - this.abbreviationLoader = Objects.requireNonNull(abbreviationLoader); + public ContentAutoCompleters() { } public ContentAutoCompleters(BibDatabase database, MetaData metaData, AutoCompletePreferences preferences, JournalAbbreviationLoader abbreviationLoader) { - this(abbreviationLoader); Objects.requireNonNull(preferences); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); + AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences, abbreviationLoader); List completeFields = preferences.getCompleteNames(); for (String field : completeFields) { AutoCompleter autoCompleter = autoCompleterFactory.getFor(field); @@ -32,7 +26,6 @@ public ContentAutoCompleters(BibDatabase database, MetaData metaData, AutoComple addDatabase(database); - addJournalListToAutoCompleter(); addContentSelectorValuesToAutoCompleters(metaData); } @@ -46,17 +39,4 @@ public void addContentSelectorValuesToAutoCompleters(MetaData metaData) { metaData.getContentSelectors(entry.getKey()).forEach(ac::addItemToIndex); } } - - /** - * If an autocompleter exists for the "journal" field, add all - * journal names in the journal abbreviation list to this autocompleter. - */ - public void addJournalListToAutoCompleter() { - AutoCompleter autoCompleter = get("journal"); - if(autoCompleter != null) { - for (Abbreviation abbreviation : abbreviationLoader.getRepository().getAbbreviations()) { - autoCompleter.addItemToIndex(abbreviation.getName()); - } - } - } } diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java b/src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java new file mode 100644 index 000000000000..51cc5afb1fd7 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2003-2016 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.autocompleter; + +import java.util.List; +import java.util.Objects; + +import net.sf.jabref.logic.journals.Abbreviation; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; + +public class JournalAutoCompleter extends EntireFieldAutoCompleter { + + private final JournalAbbreviationLoader abbreviationLoader; + + JournalAutoCompleter(String fieldName, AutoCompletePreferences preferences, JournalAbbreviationLoader abbreviationLoader) { + super(fieldName, preferences); + this.abbreviationLoader = Objects.requireNonNull(abbreviationLoader); + } + + @Override + public List complete(String toComplete) { + List completions = super.complete(toComplete); + + // Also return journal names in the journal abbreviation list + for (Abbreviation abbreviation : abbreviationLoader.getRepository().getAbbreviations()) { + if (abbreviation.getName().startsWith(toComplete)) { + completions.add(abbreviation.getName()); + } + } + + return completions; + } +} diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java index 970b5e672647..db57726272dc 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java @@ -21,18 +21,18 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.entry.BibEntry; public class CleanupWorker { private final BibDatabaseContext databaseContext; - private final JournalAbbreviationRepository repository; + private final JournalAbbreviationLoader repositoryLoader; private int unsuccessfulRenames; - public CleanupWorker(BibDatabaseContext databaseContext, JournalAbbreviationRepository repository) { + public CleanupWorker(BibDatabaseContext databaseContext, JournalAbbreviationLoader repositoryLoader) { this.databaseContext = databaseContext; - this.repository = repository; + this.repositoryLoader = repositoryLoader; } public int getUnsuccessfulRenames() { @@ -73,7 +73,7 @@ private List determineCleanupActions(CleanupPreset preset) { } if (preset.isRenamePDF()) { RenamePdfCleanup cleaner = new RenamePdfCleanup(preset.isRenamePdfOnlyRelativePaths(), databaseContext, - repository); + repositoryLoader); jobs.add(cleaner); unsuccessfulRenames += cleaner.getUnsuccessfulRenames(); } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java index b8bf7331429b..19d70a8879fb 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java @@ -23,7 +23,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.TypedBibEntry; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.ParsedFileField; @@ -32,15 +32,15 @@ public class RenamePdfCleanup implements CleanupJob { private final BibDatabaseContext databaseContext; private final boolean onlyRelativePaths; - private final JournalAbbreviationRepository repository; + private final JournalAbbreviationLoader repositoryLoader; private int unsuccessfulRenames; public RenamePdfCleanup(boolean onlyRelativePaths, BibDatabaseContext databaseContext, - JournalAbbreviationRepository repository) { + JournalAbbreviationLoader repositoryLoader) { this.databaseContext = Objects.requireNonNull(databaseContext); this.onlyRelativePaths = onlyRelativePaths; - this.repository = Objects.requireNonNull(repository); + this.repositoryLoader = Objects.requireNonNull(repositoryLoader); } @Override @@ -59,7 +59,7 @@ public List cleanup(BibEntry entry) { } StringBuilder newFilename = new StringBuilder( - FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), entry, repository)); + FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), entry, repositoryLoader)); //Add extension to newFilename newFilename.append('.').append(FileUtil.getFileExtension(realOldFilename).orElse("pdf")); diff --git a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java index 1f2e87bc767b..6db7a6d49845 100644 --- a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java @@ -218,7 +218,7 @@ public boolean contains(BibEntry entry) { * @param text The string to look in. * @return true if the word was found, false otherwise. */ - private static boolean containsWord(String word, String text) { + public static boolean containsWord(String word, String text) { int piv = 0; while (piv < text.length()) { int index = text.indexOf(word, piv); diff --git a/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java index 5f1342bb423b..b7ac873b82d0 100644 --- a/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java +++ b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java @@ -38,11 +38,6 @@ public class JournalAbbreviationLoader { private static final String JOURNALS_IEEE_ABBREVIATION_LIST_WITH_TEXT = "/journals/IEEEJournalListText.txt"; private JournalAbbreviationRepository journalAbbrev; - - public JournalAbbreviationLoader(JabRefPreferences preferences) { - update(preferences); - } - public void update(JabRefPreferences jabRefPreferences) { journalAbbrev = new JournalAbbreviationRepository(); @@ -100,6 +95,9 @@ public static List getBuiltInAbbreviations() { } public JournalAbbreviationRepository getRepository() { + if (journalAbbrev == null) { + update(Globals.prefs); + } return journalAbbrev; } diff --git a/src/main/java/net/sf/jabref/logic/layout/Layout.java b/src/main/java/net/sf/jabref/logic/layout/Layout.java index 31243bfa8e5c..7a497a5e043e 100644 --- a/src/main/java/net/sf/jabref/logic/layout/Layout.java +++ b/src/main/java/net/sf/jabref/logic/layout/Layout.java @@ -22,7 +22,7 @@ import java.util.regex.Pattern; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; @@ -41,7 +41,7 @@ public class Layout { private static final Log LOGGER = LogFactory.getLog(Layout.class); - public Layout(List parsedEntries, JournalAbbreviationRepository repository) { + public Layout(List parsedEntries, JournalAbbreviationLoader repositoryLoader) { List tmpEntries = new ArrayList<>(parsedEntries.size()); List blockEntries = null; @@ -67,7 +67,7 @@ public Layout(List parsedEntries, JournalAbbreviationRepository repos blockEntries.add(parsedEntry); le = new LayoutEntry(blockEntries, parsedEntry.i == LayoutHelper.IS_FIELD_END ? LayoutHelper.IS_FIELD_START : LayoutHelper.IS_GROUP_START, - repository); + repositoryLoader); tmpEntries.add(le); blockEntries = null; } else { @@ -82,7 +82,7 @@ public Layout(List parsedEntries, JournalAbbreviationRepository repos } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, repository)); + tmpEntries.add(new LayoutEntry(parsedEntry, repositoryLoader)); } else { blockEntries.add(parsedEntry); } diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java index c2678b9b4073..e16b1d99f868 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java @@ -29,7 +29,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.format.AuthorAbbreviator; import net.sf.jabref.logic.layout.format.AuthorAndsCommaReplacer; import net.sf.jabref.logic.layout.format.AuthorAndsReplacer; @@ -116,10 +116,10 @@ class LayoutEntry { private static final Log LOGGER = LogFactory.getLog(LayoutEntry.class); - private final JournalAbbreviationRepository repository; + private final JournalAbbreviationLoader repositoryLoader; - public LayoutEntry(StringInt si, JournalAbbreviationRepository repository) { - this.repository = repository; + public LayoutEntry(StringInt si, JournalAbbreviationLoader repositoryLoader) { + this.repositoryLoader = repositoryLoader; type = si.i; switch (type) { case LayoutHelper.IS_LAYOUT_TEXT: @@ -138,8 +138,8 @@ public LayoutEntry(StringInt si, JournalAbbreviationRepository repository) { } } - public LayoutEntry(List parsedEntries, int layoutType, JournalAbbreviationRepository repository) { - this.repository = repository; + public LayoutEntry(List parsedEntries, int layoutType, JournalAbbreviationLoader repositoryLoader) { + this.repositoryLoader = repositoryLoader; List tmpEntries = new ArrayList<>(); String blockStart = parsedEntries.get(0).s; String blockEnd = parsedEntries.get(parsedEntries.size() - 1).s; @@ -164,7 +164,7 @@ public LayoutEntry(List parsedEntries, int layoutType, JournalAbbrevi blockEntries.add(parsedEntry); int groupType = parsedEntry.i == LayoutHelper.IS_GROUP_END ? LayoutHelper.IS_GROUP_START : LayoutHelper.IS_FIELD_START; - LayoutEntry le = new LayoutEntry(blockEntries, groupType, repository); + LayoutEntry le = new LayoutEntry(blockEntries, groupType, repositoryLoader); tmpEntries.add(le); blockEntries = null; } else { @@ -180,7 +180,7 @@ public LayoutEntry(List parsedEntries, int layoutType, JournalAbbrevi } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, repository)); + tmpEntries.add(new LayoutEntry(parsedEntry, repositoryLoader)); } else { blockEntries.add(parsedEntry); } @@ -507,7 +507,7 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { case "Iso690NamesAuthors": return new Iso690NamesAuthors(); case "JournalAbbreviator": - return new JournalAbbreviator(repository); + return new JournalAbbreviator(repositoryLoader); case "LastPage": return new LastPage(); case "FormatChars": // For backward compatibility diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java b/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java index fe5afdd095fc..59785ea4f641 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; /** * Helper class to get a Layout object. @@ -50,13 +50,13 @@ public class LayoutHelper { private final PushbackReader in; private final List parsedEntries = new ArrayList<>(); - private final JournalAbbreviationRepository repository; + private final JournalAbbreviationLoader repositoryLoader; private boolean endOfFile; - public LayoutHelper(Reader in, JournalAbbreviationRepository repository) { + public LayoutHelper(Reader in, JournalAbbreviationLoader repositoryLoader) { this.in = new PushbackReader(Objects.requireNonNull(in)); - this.repository = Objects.requireNonNull(repository); + this.repositoryLoader = Objects.requireNonNull(repositoryLoader); } public Layout getLayoutFromText() throws IOException { @@ -70,7 +70,7 @@ public Layout getLayoutFromText() throws IOException { } } - return new Layout(parsedEntries, repository); + return new Layout(parsedEntries, repositoryLoader); } public static String getCurrentGroup() { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java b/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java index f62cefacbae1..59a7a25ede5b 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java @@ -29,7 +29,7 @@ import java.util.Objects; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.LayoutFormatter; /** @@ -49,15 +49,15 @@ */ public class JournalAbbreviator implements LayoutFormatter { - private final JournalAbbreviationRepository repostiory; + private final JournalAbbreviationLoader repostioryLoader; - public JournalAbbreviator(JournalAbbreviationRepository repostiory) { - this.repostiory = Objects.requireNonNull(repostiory); + public JournalAbbreviator(JournalAbbreviationLoader repostioryLoader) { + this.repostioryLoader = Objects.requireNonNull(repostioryLoader); } @Override public String format(String fieldText) { - return repostiory.getIsoAbbreviation(fieldText).orElse(fieldText); + return repostioryLoader.getRepository().getIsoAbbreviation(fieldText).orElse(fieldText); } } diff --git a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java index 17f35203b301..7488671a7f1a 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java @@ -37,7 +37,7 @@ import java.util.regex.Pattern; import net.sf.jabref.JabRefMain; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.logic.layout.LayoutHelper; @@ -146,14 +146,14 @@ enum BibStyleMode { private static final String AUTHOR_LAST_SEPARATOR = "AuthorLastSeparator"; private static final String AUTHOR_SEPARATOR = "AuthorSeparator"; - private final JournalAbbreviationRepository repository; + private final JournalAbbreviationLoader repositoryLoader; private static final Pattern QUOTED = Pattern.compile("\".*\""); private static final Log LOGGER = LogFactory.getLog(OOBibStyle.class); - public OOBibStyle(File styleFile, JournalAbbreviationRepository repository, Charset encoding) throws IOException { - this.repository = Objects.requireNonNull(repository); + public OOBibStyle(File styleFile, JournalAbbreviationLoader repositoryLoader, Charset encoding) throws IOException { + this.repositoryLoader = Objects.requireNonNull(repositoryLoader); this.styleFile = Objects.requireNonNull(styleFile); this.encoding = Objects.requireNonNull(encoding); setDefaultProperties(); @@ -162,9 +162,9 @@ public OOBibStyle(File styleFile, JournalAbbreviationRepository repository, Char path = styleFile.getPath(); } - public OOBibStyle(String resourcePath, JournalAbbreviationRepository repository) + public OOBibStyle(String resourcePath, JournalAbbreviationLoader repositoryLoader) throws IOException { - this.repository = Objects.requireNonNull(repository); + this.repositoryLoader = Objects.requireNonNull(repositoryLoader); this.encoding = StandardCharsets.UTF_8; setDefaultProperties(); initialize(JabRefMain.class.getResource(resourcePath).openStream()); @@ -378,7 +378,7 @@ private void handleStructureLine(String line) { boolean setDefault = line.substring(0, index).equals(OOBibStyle.DEFAULT_MARK); String type = line.substring(0, index); try { - Layout layout = new LayoutHelper(new StringReader(formatString), this.repository).getLayoutFromText(); + Layout layout = new LayoutHelper(new StringReader(formatString), this.repositoryLoader).getLayoutFromText(); if (setDefault) { defaultBibLayout = layout; } else { diff --git a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java index f945b8053aac..af1a616d643e 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java @@ -24,7 +24,7 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -40,7 +40,7 @@ public class StyleLoader { private final List internalStyleFiles = Arrays.asList(DEFAULT_AUTHORYEAR_STYLE_PATH, DEFAULT_NUMERICAL_STYLE_PATH); - private final JournalAbbreviationRepository repository; + private final JournalAbbreviationLoader journalAbbreviationLoader; private final OpenOfficePreferences preferences; private final Charset encoding; @@ -50,8 +50,8 @@ public class StyleLoader { private final List externalStyles = new ArrayList<>(); - public StyleLoader(OpenOfficePreferences preferences, JournalAbbreviationRepository repository, Charset encoding) { - this.repository = Objects.requireNonNull(repository); + public StyleLoader(OpenOfficePreferences preferences, JournalAbbreviationLoader journalAbbreviationLoader, Charset encoding) { + this.journalAbbreviationLoader = Objects.requireNonNull(journalAbbreviationLoader); this.preferences = Objects.requireNonNull(preferences); this.encoding = Objects.requireNonNull(encoding); loadInternalStyles(); @@ -72,7 +72,7 @@ public List getStyles() { public boolean addStyleIfValid(String filename) { Objects.requireNonNull(filename); try { - OOBibStyle newStyle = new OOBibStyle(new File(filename), repository, encoding); + OOBibStyle newStyle = new OOBibStyle(new File(filename), journalAbbreviationLoader, encoding); if (externalStyles.contains(newStyle)) { LOGGER.info("External style file " + filename + " already existing."); } else if (newStyle.isValid()) { @@ -98,7 +98,7 @@ private void loadExternalStyles() { List lists = preferences.getExternalStyles(); for (String filename : lists) { try { - OOBibStyle style = new OOBibStyle(new File(filename), repository, encoding); + OOBibStyle style = new OOBibStyle(new File(filename), journalAbbreviationLoader, encoding); if (style.isValid()) { //Problem! externalStyles.add(style); } else { @@ -117,7 +117,7 @@ private void loadInternalStyles() { internalStyles.clear(); for (String filename : internalStyleFiles) { try { - internalStyles.add(new OOBibStyle(filename, repository)); + internalStyles.add(new OOBibStyle(filename, journalAbbreviationLoader)); } catch (IOException e) { LOGGER.info("Problem reading internal style file " + filename, e); } 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 bc165632dcfb..09a380a9669f 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 @@ -39,7 +39,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.util.OS; @@ -386,15 +386,16 @@ public static List getListOfLinkedFiles(List bes, List f * * @param database the database, where the entry is located * @param entry the entry to which the file should be linked to - * @param repository + * @param repositoryLoader * @return a suggested fileName */ - public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, JournalAbbreviationRepository repository) { + public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, + JournalAbbreviationLoader repositoryLoader) { String targetName = entry.getCiteKey() == null ? "default" : entry.getCiteKey(); StringReader sr = new StringReader(Globals.prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)); Layout layout = null; try { - layout = new LayoutHelper(sr, repository).getLayoutFromText(); + layout = new LayoutHelper(sr, repositoryLoader).getLayoutFromText(); } catch (IOException e) { LOGGER.info("Wrong format " + e.getMessage(), e); } diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 7a14564f8120..9bfc08973457 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -190,6 +190,7 @@ public Set getFieldNames() { /** * Returns the contents of the given field, or null if it is not set. */ + @Deprecated //Use getFieldOptional instead public String getField(String name) { return fields.get(toLowerCase(name)); } diff --git a/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java b/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java index e9666151e02d..17c1d0d36363 100644 --- a/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java +++ b/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java @@ -46,7 +46,7 @@ public ExportFormatTest(IExportFormat format, String name) { @Before public void setUp() { - Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(Globals.prefs); + Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(); databaseContext = new BibDatabaseContext(new BibDatabase(), new MetaData()); charset = Charsets.UTF_8; entries = Collections.emptyList(); diff --git a/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java b/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java index 9bdbb2c18c54..d72385d23c02 100644 --- a/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java +++ b/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java @@ -38,7 +38,7 @@ public void setUp() { ExportFormats.initAllExports(); exportFormat = ExportFormats.getExportFormat("html"); - Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(Globals.prefs); + Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(); databaseContext = new BibDatabaseContext(new BibDatabase(), new MetaData()); charset = Charsets.UTF_8; BibEntry entry = new BibEntry(); diff --git a/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java b/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java index 5b782a771f92..5c2d8eddd127 100644 --- a/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java +++ b/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java @@ -1,76 +1,73 @@ package net.sf.jabref.logic.autocompleter; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; + import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import static org.mockito.Mockito.mock; public class AutoCompleterFactoryTest { + private AutoCompleterFactory autoCompleterFactory; + private JournalAbbreviationLoader abbreviationLoader; + + @Before + public void setUp() throws Exception { + AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); + abbreviationLoader = mock(JournalAbbreviationLoader.class); + autoCompleterFactory = new AutoCompleterFactory(preferences, abbreviationLoader); + } + @Test(expected = NullPointerException.class) public void initFactoryWithNullPreferenceThrowsException() { - new AutoCompleterFactory(null); + new AutoCompleterFactory(null, abbreviationLoader); } @Test public void getForUnknownFieldReturnsDefaultAutoCompleter() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); AutoCompleter autoCompleter = autoCompleterFactory.getFor("unknownField"); Assert.assertTrue(autoCompleter instanceof DefaultAutoCompleter); } @Test(expected = NullPointerException.class) public void getForNullThrowsException() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); autoCompleterFactory.getFor(null); } @Test public void getForAuthorReturnsNameFieldAutoCompleter() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); AutoCompleter autoCompleter = autoCompleterFactory.getFor("author"); Assert.assertTrue(autoCompleter instanceof NameFieldAutoCompleter); } @Test public void getForEditorReturnsNameFieldAutoCompleter() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); AutoCompleter autoCompleter = autoCompleterFactory.getFor("editor"); Assert.assertTrue(autoCompleter instanceof NameFieldAutoCompleter); } @Test public void getForCrossrefReturnsBibtexKeyAutoCompleter() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); AutoCompleter autoCompleter = autoCompleterFactory.getFor("crossref"); Assert.assertTrue(autoCompleter instanceof BibtexKeyAutoCompleter); } @Test public void getForJournalReturnsEntireFieldAutoCompleter() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); AutoCompleter autoCompleter = autoCompleterFactory.getFor("journal"); Assert.assertTrue(autoCompleter instanceof EntireFieldAutoCompleter); } @Test public void getForPublisherReturnsEntireFieldAutoCompleter() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); AutoCompleter autoCompleter = autoCompleterFactory.getFor("publisher"); Assert.assertTrue(autoCompleter instanceof EntireFieldAutoCompleter); } @Test public void getPersonAutoCompleterReturnsNameFieldAutoCompleter() { - AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); - AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(preferences); AutoCompleter autoCompleter = autoCompleterFactory.getPersonAutoCompleter(); Assert.assertTrue(autoCompleter instanceof NameFieldAutoCompleter); } diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index 12529c4836dc..b8e547734ea2 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -21,7 +21,6 @@ import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FileField; @@ -59,7 +58,7 @@ public void setUp() throws IOException { MetaData metaData = new MetaData(); metaData.setDefaultFileDirectory(pdfFolder.getAbsolutePath()); BibDatabaseContext context = new BibDatabaseContext(new BibDatabase(), metaData, bibFolder.newFile("test.bib")); - worker = new CleanupWorker(context, mock(JournalAbbreviationRepository.class)); + worker = new CleanupWorker(context, mock(JournalAbbreviationLoader.class)); } diff --git a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java index df150f34c43e..f80dd8ed1aa1 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java @@ -9,7 +9,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FileField; @@ -53,7 +53,7 @@ public void cleanupRenamePdfRenamesFileEvenIfOnlyDifferenceIsCase() throws IOExc ParsedFileField fileField = new ParsedFileField("", tempFile.getAbsolutePath(), ""); entry.setField("file", FileField.getStringRepresentation(fileField)); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationRepository.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot.tmp", ""); @@ -69,7 +69,7 @@ public void cleanupRenamePdfRenamesWithMultipleFiles() throws IOException { entry.setField("file", FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), new ParsedFileField("", tempFile.getAbsolutePath(), ""), new ParsedFileField("","","")))); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationRepository.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); cleanup.cleanup(entry); assertEquals(FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), @@ -84,7 +84,7 @@ public void cleanupRenamePdfRenamesFileStartingWithBibtexKey() throws IOExceptio entry.setField("file", FileField.getStringRepresentation(fileField)); entry.setField("title", "test title"); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationRepository.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot - test title.tmp", ""); @@ -99,7 +99,7 @@ public void cleanupRenamePdfRenamesFileInSameFolder() throws IOException { entry.setField("file", FileField.getStringRepresentation(fileField)); entry.setField("title", "test title"); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationRepository.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot - test title.pdf", "PDF"); diff --git a/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java b/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java index 5dc79f2edb63..6ba66c28daf2 100644 --- a/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java +++ b/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java @@ -1,54 +1,58 @@ package net.sf.jabref.logic.journals; +import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +@RunWith(MockitoJUnitRunner.class) public class AbbreviationsTest { + @Mock JabRefPreferences prefs; + JournalAbbreviationLoader abbreviations; + + @Before + public void setUp() throws Exception { + Globals.prefs = prefs; + abbreviations = new JournalAbbreviationLoader(); + } + @Test public void getNextAbbreviationAbbreviatesIEEEJournalTitle() { - JabRefPreferences prefs = mock(JabRefPreferences.class); when(prefs.getBoolean(JabRefPreferences.USE_IEEE_ABRV)).thenReturn(true); - JournalAbbreviationLoader abbreviations = new JournalAbbreviationLoader(prefs); assertEquals("#IEEE_J_PROC#", abbreviations.getRepository().getNextAbbreviation("Proceedings of the IEEE").get()); } @Test public void getNextAbbreviationExpandsIEEEAbbreviation() { - JabRefPreferences prefs = mock(JabRefPreferences.class); when(prefs.getBoolean(JabRefPreferences.USE_IEEE_ABRV)).thenReturn(true); - JournalAbbreviationLoader abbreviations = new JournalAbbreviationLoader(prefs); assertEquals("Proceedings of the IEEE", abbreviations.getRepository().getNextAbbreviation("#IEEE_J_PROC#").get()); } @Test public void getNextAbbreviationAbbreviatesJournalTitle() { - JabRefPreferences prefs = mock(JabRefPreferences.class); - JournalAbbreviationLoader abbreviations = new JournalAbbreviationLoader(prefs); assertEquals("Proc. IEEE", abbreviations.getRepository().getNextAbbreviation("Proceedings of the IEEE").get()); } @Test public void getNextAbbreviationRemovesPoint() { - JabRefPreferences prefs = mock(JabRefPreferences.class); - JournalAbbreviationLoader abbreviations = new JournalAbbreviationLoader(prefs); assertEquals("Proc IEEE", abbreviations.getRepository().getNextAbbreviation("Proc. IEEE").get()); } @Test public void getNextAbbreviationExpandsAbbreviation() { - JabRefPreferences prefs = mock(JabRefPreferences.class); - JournalAbbreviationLoader abbreviations = new JournalAbbreviationLoader(prefs); assertEquals("Proceedings of the IEEE", abbreviations.getRepository().getNextAbbreviation("Proc IEEE").get()); } diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java index 5143be29781c..39602d0d654f 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java @@ -7,7 +7,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -86,7 +86,7 @@ public void setUp() { public String layout(String layoutFile, BibEntry entry, Optional highlightPattern) throws IOException { StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); - Layout layout = new LayoutHelper(sr, mock(JournalAbbreviationRepository.class)).getLayoutFromText(); + Layout layout = new LayoutHelper(sr, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); return layout.doLayout(entry, null, highlightPattern); } diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java index 5f5e523318b6..c10db239cbd7 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java @@ -8,7 +8,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -53,7 +53,7 @@ public String layout(String layoutFile, String entry) throws IOException { BibEntry be = LayoutTest.bibtexString2BibtexEntry(entry); StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); - Layout layout = new LayoutHelper(sr, mock(JournalAbbreviationRepository.class)).getLayoutFromText(); + Layout layout = new LayoutHelper(sr, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); return layout.doLayout(be, null); } diff --git a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java index 2626ebe43fa9..0b4851dc049a 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java @@ -19,13 +19,14 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.importer.fileformat.ImportFormat; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -49,7 +50,7 @@ public void tearDown() { @Test public void testAuthorYear() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertTrue(style.isValid()); assertTrue(style.isFromResource()); assertFalse(style.isBibtexKeyCiteMarkers()); @@ -66,7 +67,7 @@ public void testAuthorYearAsFile() throws URISyntaxException, IOException { File defFile = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile(); - OOBibStyle style = new OOBibStyle(defFile, mock(JournalAbbreviationRepository.class), + OOBibStyle style = new OOBibStyle(defFile, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertTrue(style.isValid()); assertFalse(style.isFromResource()); @@ -82,7 +83,7 @@ public void testAuthorYearAsFile() throws URISyntaxException, IOException { public void testNumerical() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertTrue(style.isValid()); assertFalse(style.isBibtexKeyCiteMarkers()); assertFalse(style.isBoldCitations()); @@ -96,7 +97,7 @@ public void testNumerical() throws IOException { @Test public void testGetNumCitationMarker() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertEquals("[1] ", style.getNumCitationMarker(Arrays.asList(1), -1, true)); assertEquals("[1]", style.getNumCitationMarker(Arrays.asList(1), -1, false)); assertEquals("[1] ", style.getNumCitationMarker(Arrays.asList(1), 0, true)); @@ -113,7 +114,7 @@ public void testGetNumCitationMarker() throws IOException { @Test public void testGetNumCitationMarkerUndefined() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "; 2-4] ", style.getNumCitationMarker(Arrays.asList(4, 2, 3, 0), 1, true)); @@ -131,7 +132,7 @@ public void testGetNumCitationMarkerUndefined() throws IOException { @Test public void testGetCitProperty() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertEquals(", ", style.getStringCitProperty("AuthorSeparator")); assertEquals(3, style.getIntCitProperty("MaxAuthors")); assertTrue(style.getBooleanCitProperty(OOBibStyle.MULTI_CITE_CHRONOLOGICAL)); @@ -146,7 +147,7 @@ public void testGetCitationMarker() throws IOException { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); BibDatabase db = result.getDatabase(); for (BibEntry entry : db.getEntries()) { @@ -167,7 +168,7 @@ public void testLayout() throws IOException { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); BibDatabase db = result.getDatabase(); Layout l = style.getReferenceFormat("default"); @@ -187,7 +188,7 @@ public void testLayout() throws IOException { @Test public void testInstitutionAuthor() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); BibDatabase database = new BibDatabase(); Layout l = style.getReferenceFormat("article"); @@ -206,7 +207,7 @@ public void testInstitutionAuthor() throws IOException { @Test public void testVonAuthor() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); BibDatabase database = new BibDatabase(); Layout l = style.getReferenceFormat("article"); @@ -225,7 +226,7 @@ public void testVonAuthor() throws IOException { @Test public void testInstitutionAuthorMarker() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -245,7 +246,7 @@ public void testInstitutionAuthorMarker() throws IOException { @Test public void testVonAuthorMarker() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -265,7 +266,7 @@ public void testVonAuthorMarker() throws IOException { @Test public void testNullAuthorMarker() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -283,7 +284,7 @@ public void testNullAuthorMarker() throws IOException { @Test public void testNullYearMarker() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -301,7 +302,7 @@ public void testNullYearMarker() throws IOException { @Test public void testEmptyEntryMarker() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -318,7 +319,7 @@ public void testEmptyEntryMarker() throws IOException { @Test public void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -354,7 +355,7 @@ public void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { @Test public void testGetCitationMarkerInTextUniquefiers() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -390,7 +391,7 @@ public void testGetCitationMarkerInTextUniquefiers() throws IOException { @Test public void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -425,7 +426,7 @@ public void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throw @Test public void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -461,9 +462,9 @@ public void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOExc // TODO: equals only work when initialized from file, not from reader public void testEquals() throws IOException { OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertEquals(style1, style2); } @@ -471,35 +472,36 @@ public void testEquals() throws IOException { // TODO: equals only work when initialized from file, not from reader public void testNotEquals() throws IOException { OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertNotEquals(style1, style2); } @Test public void testCompareToEqual() throws IOException { OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertEquals(0, style1.compareTo(style2)); } @Test public void testCompareToNotEqual() throws IOException { OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, - mock(JournalAbbreviationRepository.class)); + mock(JournalAbbreviationLoader.class)); assertTrue(style1.compareTo(style2) > 0); assertFalse(style2.compareTo(style1) > 0); } - + @Test + @Ignore public void testEmptyStringPropertyAndOxfordComma() throws URISyntaxException, IOException { String fileName = Paths.get(OOBibStyleTest.class.getResource("test.jstyle").toURI()).toString(); - OOBibStyle style = new OOBibStyle(fileName, mock(JournalAbbreviationRepository.class)); + OOBibStyle style = new OOBibStyle(fileName, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); BibDatabase database = new BibDatabase(); diff --git a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java index c4c9c27a24bf..9e2cfd984e13 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java @@ -11,7 +11,6 @@ import net.sf.jabref.JabRefMain; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; -import net.sf.jabref.logic.journals.JournalAbbreviationRepository; import org.junit.After; import org.junit.Before; @@ -50,7 +49,7 @@ public void tearDown() throws Exception { @Test(expected = NullPointerException.class) public void throwNPEWithNullPreferences() { loader = new StyleLoader(null, - mock(JournalAbbreviationRepository.class), mock(Charset.class)); + mock(JournalAbbreviationLoader.class), mock(Charset.class)); fail(); } @@ -64,7 +63,7 @@ public void throwNPEWithNullRepository() { @Test(expected = NullPointerException.class) public void throwNPEWithNullCharset() { loader = new StyleLoader(mock(OpenOfficePreferences.class), - mock(JournalAbbreviationRepository.class), null); + mock(JournalAbbreviationLoader.class), null); fail(); } @@ -72,7 +71,7 @@ public void throwNPEWithNullCharset() { public void testGetStylesWithEmptyExternal() { preferences.setExternalStyles(Collections.emptyList()); loader = new StyleLoader(preferences, - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertEquals(2, loader.getStyles().size()); } @@ -81,7 +80,7 @@ public void testGetStylesWithEmptyExternal() { public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); loader = new StyleLoader(preferences, - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); @@ -94,7 +93,7 @@ public void testAddInvalidStyleLeadsToNoMoreStyle() { preferences.setExternalStyles(Collections.emptyList()); Globals.prefs.putStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES, Collections.emptyList()); loader = new StyleLoader(preferences, - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); int beforeAdding = loader.getStyles().size(); loader.addStyleIfValid("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky"); assertEquals(beforeAdding, loader.getStyles().size()); @@ -106,7 +105,7 @@ public void testInitalizeWithOneExternalFile() throws URISyntaxException { .toFile().getPath(); preferences.setExternalStyles(Collections.singletonList(filename)); loader = new StyleLoader(preferences, - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertEquals(numberOfInternalStyles + 1, loader.getStyles().size()); } @@ -115,7 +114,7 @@ public void testInitalizeWithIncorrectExternalFile() { preferences.setExternalStyles(Collections.singletonList("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky")); loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertEquals(numberOfInternalStyles, loader.getStyles().size()); } @@ -126,7 +125,7 @@ public void testInitalizeWithOneExternalFileRemoveStyle() throws URISyntaxExcept preferences.setExternalStyles(Collections.singletonList(filename)); loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); int beforeRemoving = loader.getStyles().size(); for (OOBibStyle style : loader.getStyles()) { @@ -148,7 +147,7 @@ public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() thro preferences.setExternalStyles(Collections.singletonList(filename)); loader = new StyleLoader(preferences, - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { if (!style.isFromResource()) { @@ -166,7 +165,7 @@ public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() thro public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); int beforeAdding = loader.getStyles().size(); String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); @@ -178,7 +177,7 @@ public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException @Test(expected = NullPointerException.class) public void testAddNullStyleThrowsNPE() { loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); loader.addStyleIfValid(null); fail(); } @@ -188,7 +187,7 @@ public void testAddNullStyleThrowsNPE() { public void testGetDefaultUsedStyleWhenEmpty() { Globals.prefs.remove(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE); loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, style.getPath()); @@ -199,7 +198,7 @@ public void testGetDefaultUsedStyleWhenEmpty() { public void testGetStoredUsedStyle() { preferences.setCurrentStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH); loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, style.getPath()); @@ -210,7 +209,7 @@ public void testGetStoredUsedStyle() { public void testGtDefaultUsedStyleWhenIncorrect() { preferences.setCurrentStyle("ljlkjlkjnljnvdlsjniuhwelfhuewfhlkuewhfuwhelu"); loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), - mock(JournalAbbreviationRepository.class), Globals.prefs.getDefaultEncoding()); + mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, style.getPath()); @@ -221,7 +220,7 @@ public void testGtDefaultUsedStyleWhenIncorrect() { public void testRemoveInternalStyleReturnsFalseAndDoNotRemove() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, mock(JournalAbbreviationRepository.class), + loader = new StyleLoader(preferences, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { diff --git a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java index 8a74ee0dde27..925f418fa4ed 100644 --- a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java @@ -23,7 +23,6 @@ public class FileUtilTest { @Before public void setUp() { Globals.prefs = mock(JabRefPreferences.class); - Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(Globals.prefs); } @After @@ -41,7 +40,7 @@ public void testGetLinkedFileNameDefault() { entry.setCiteKey("1234"); entry.setField("title", "mytitle"); - assertEquals("1234 - mytitle", FileUtil.createFileNameFromPattern(null, entry, Globals.journalAbbreviationLoader.getRepository())); + assertEquals("1234 - mytitle", FileUtil.createFileNameFromPattern(null, entry, mock(JournalAbbreviationLoader.class))); } @Test @@ -53,7 +52,7 @@ public void testGetLinkedFileNameBibTeXKey() { entry.setCiteKey("1234"); entry.setField("title", "mytitle"); - assertEquals("1234", FileUtil.createFileNameFromPattern(null, entry, Globals.journalAbbreviationLoader.getRepository())); + assertEquals("1234", FileUtil.createFileNameFromPattern(null, entry, mock(JournalAbbreviationLoader.class))); } @Test @@ -130,4 +129,4 @@ public void uniquePathSubstrings() { } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/model/entry/BibEntryTest.java b/src/test/java/net/sf/jabref/model/entry/BibEntryTest.java index 6e1c41fca84b..d89ee609e47f 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibEntryTest.java +++ b/src/test/java/net/sf/jabref/model/entry/BibEntryTest.java @@ -1,6 +1,9 @@ package net.sf.jabref.model.entry; +import java.util.Optional; + import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -26,4 +29,11 @@ public void notOverrideReservedFields() { public void notClearReservedFields() { entry.clearField(BibEntry.ID_FIELD); } -} \ No newline at end of file + + @Test + public void getFieldIsCaseInsensitive() throws Exception { + entry.setField("TeSt", "value"); + + Assert.assertEquals(Optional.of("value"), entry.getFieldOptional("tEsT")); + } +} From 8db7f86ec2dfb72dd6fdc6b16e62c548595728e1 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 28 Jun 2016 15:50:43 +0200 Subject: [PATCH 163/268] Fixes #1507: Keywords are now separated by the delimiter specified in the preferences (#1511) * Fixes #1507: Keywords are now separated by the delimiter specified in the preferences * Change keywords to set and move Fieldchange to model * Fix SpecialFieldUtils * Use Set inteface instead of LinkedHashSet as return values * Fix import order --- CHANGELOG.md | 1 + .../java/net/sf/jabref/JabRefPreferences.java | 4 +- .../sf/jabref/event/FieldChangedEvent.java | 5 + .../sf/jabref/exporter/BibDatabaseWriter.java | 2 +- .../exporter/FieldFormatterCleanups.java | 2 +- .../net/sf/jabref/exporter/SaveSession.java | 2 +- .../java/net/sf/jabref/gui/BasePanel.java | 2 +- .../sf/jabref/gui/actions/CleanupAction.java | 2 +- .../gui/actions/ManageKeywordsAction.java | 38 +++----- .../sf/jabref/gui/groups/GroupSelector.java | 3 +- .../groups/UndoableChangeEntriesOfGroup.java | 2 +- .../jabref/gui/preftabs/GroupsPrefsTab.java | 4 +- .../jabref/gui/undo/UndoableFieldChange.java | 2 +- .../importer/fetcher/IEEEXploreFetcher.java | 2 +- .../importer/fileformat/JSONEntryParser.java | 3 +- .../importer/fileformat/RepecNepImporter.java | 3 +- .../net/sf/jabref/logic/TypedBibEntry.java | 1 + .../jabref/logic/cleanup/BiblatexCleanup.java | 2 +- .../sf/jabref/logic/cleanup/CleanupJob.java | 4 +- .../jabref/logic/cleanup/CleanupWorker.java | 2 +- .../sf/jabref/logic/cleanup/DoiCleanup.java | 2 +- .../logic/cleanup/FieldFormatterCleanup.java | 2 +- .../logic/cleanup/FileLinksCleanup.java | 2 +- .../logic/cleanup/MoveFilesCleanup.java | 2 +- .../logic/cleanup/RelativePathsCleanup.java | 2 +- .../logic/cleanup/RenamePdfCleanup.java | 2 +- .../cleanup/UpgradePdfPsToFileCleanup.java | 2 +- .../logic/groups/EntriesGroupChange.java | 2 +- .../sf/jabref/logic/groups/KeywordGroup.java | 6 +- .../logic/labelpattern/LabelPatternUtil.java | 16 +++- .../logic/layout/format/RisKeywords.java | 10 +- .../net/sf/jabref/logic/util/UpdateField.java | 2 +- .../sf/jabref/logic/util/date/TimeStamp.java | 2 +- .../migrations/FileLinksUpgradeWarning.java | 2 +- .../jabref/{logic => model}/FieldChange.java | 19 +++- .../net/sf/jabref/model/entry/BibEntry.java | 92 ++++++++++--------- .../net/sf/jabref/model/entry/EntryUtil.java | 20 ++-- .../specialfields/SpecialFieldsUtils.java | 31 ++++--- .../logic/cleanup/CleanupWorkerTest.java | 2 +- .../sf/jabref/logic/util/UpdateFieldTest.java | 2 +- ...btexEntryTests.java => BibEntryTests.java} | 60 ++++++++---- .../sf/jabref/model/entry/EntryUtilTest.java | 9 +- 42 files changed, 218 insertions(+), 157 deletions(-) rename src/main/java/net/sf/jabref/{logic => model}/FieldChange.java (73%) rename src/test/java/net/sf/jabref/model/entry/{BibtexEntryTests.java => BibEntryTests.java} (82%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7ec24425971..b199b3e24b4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1434](https://github.com/JabRef/jabref/issues/1434): Static groups are now longer displayed as dynamic ones - Fixed [#1482](https://github.com/JabRef/jabref/issues/1482): Correct number of matched entries is displayed for refining subgroups - Fixed [#1444](https://github.com/JabRef/jabref/issues/1444): Implement getExtension and getDescription for importers. +- Fixed [#1507](https://github.com/JabRef/jabref/issues/1507): Keywords are now separated by the delimiter specified in the preferences ### Removed diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index 8341a5b12087..c4d73e38bff4 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -202,7 +202,7 @@ public class JabRefPreferences { public static final String GROUP_INTERSECT_SELECTIONS = "groupIntersectSelections"; public static final String GROUP_FLOAT_SELECTIONS = "groupFloatSelections"; public static final String EDIT_GROUP_MEMBERSHIP_MODE = "groupEditGroupMembershipMode"; - public static final String GROUP_KEYWORD_SEPARATOR = "groupKeywordSeparator"; + public static final String KEYWORD_SEPARATOR = "groupKeywordSeparator"; public static final String AUTO_ASSIGN_GROUP = "autoAssignGroup"; public static final String LIST_OF_FILE_COLUMNS = "listOfFileColumns"; public static final String EXTRA_FILE_COLUMNS = "extraFileColumns"; @@ -617,7 +617,7 @@ private JabRefPreferences() { defaults.put(GROUP_AUTO_HIDE, Boolean.TRUE); defaults.put(GROUP_SHOW_NUMBER_OF_ELEMENTS, Boolean.FALSE); defaults.put(AUTO_ASSIGN_GROUP, Boolean.TRUE); - defaults.put(GROUP_KEYWORD_SEPARATOR, ", "); + defaults.put(KEYWORD_SEPARATOR, ", "); defaults.put(EDIT_GROUP_MEMBERSHIP_MODE, Boolean.FALSE); defaults.put(HIGHLIGHT_GROUPS_MATCHING, "all"); defaults.put(TOOLBAR_VISIBLE, Boolean.TRUE); diff --git a/src/main/java/net/sf/jabref/event/FieldChangedEvent.java b/src/main/java/net/sf/jabref/event/FieldChangedEvent.java index c5c302ceefa4..3ae28e8f7ba7 100644 --- a/src/main/java/net/sf/jabref/event/FieldChangedEvent.java +++ b/src/main/java/net/sf/jabref/event/FieldChangedEvent.java @@ -1,5 +1,6 @@ package net.sf.jabref.event; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; /** @@ -21,6 +22,10 @@ public FieldChangedEvent(BibEntry bibEntry, String fieldName, String newValue) { this.newValue = newValue; } + public FieldChangedEvent(FieldChange fieldChange) { + this(fieldChange.getEntry(), fieldChange.getField(), fieldChange.getNewValue()); + } + public String getFieldName() { return fieldName; } diff --git a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java index 72925e078ffd..06f93c7d2885 100644 --- a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java @@ -35,7 +35,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.MetaData; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.bibtex.comparator.BibtexStringComparator; @@ -46,6 +45,7 @@ import net.sf.jabref.logic.id.IdComparator; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.EntryTypes; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; diff --git a/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java b/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java index 52d3d7ee70aa..dcb44ddc88cd 100644 --- a/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java +++ b/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java @@ -9,7 +9,6 @@ import java.util.StringJoiner; import net.sf.jabref.Globals; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.formatter.Formatters; @@ -18,6 +17,7 @@ import net.sf.jabref.logic.formatter.bibtexfields.NormalizePagesFormatter; import net.sf.jabref.logic.formatter.bibtexfields.OrdinalsToSuperscriptFormatter; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; public class FieldFormatterCleanups { diff --git a/src/main/java/net/sf/jabref/exporter/SaveSession.java b/src/main/java/net/sf/jabref/exporter/SaveSession.java index 80deb6ee114b..81a23852e6cf 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveSession.java +++ b/src/main/java/net/sf/jabref/exporter/SaveSession.java @@ -24,10 +24,10 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileBasedLock; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.FieldChange; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 711ee6799b9e..61d36f485dd1 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -112,7 +112,6 @@ import net.sf.jabref.gui.worker.SendAsEMailAction; import net.sf.jabref.gui.worker.Worker; import net.sf.jabref.importer.AppendDatabaseAction; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.autocompleter.AutoCompletePreferences; import net.sf.jabref.logic.autocompleter.AutoCompleter; import net.sf.jabref.logic.autocompleter.AutoCompleterFactory; @@ -125,6 +124,7 @@ import net.sf.jabref.logic.util.UpdateField; import net.sf.jabref.logic.util.io.FileBasedLock; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java index fae0ac0aba1b..d160b029324b 100644 --- a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java @@ -30,10 +30,10 @@ import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.gui.util.component.CheckBoxMessage; 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.FieldChange; import net.sf.jabref.model.entry.BibEntry; public class CleanupAction extends AbstractWorker { diff --git a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java index 4b2763b653a2..5c1c7a570195 100644 --- a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java @@ -23,7 +23,7 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.List; -import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -52,6 +52,7 @@ import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.logic.autocompleter.AutoCompleter; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; @@ -65,12 +66,13 @@ import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; +import static net.sf.jabref.model.entry.BibEntry.KEYWORDS_FIELD; + /** * An Action for launching keyword managing dialog * */ public class ManageKeywordsAction extends MnemonicAwareAction { - private static final String KEYWORDS_FIELD = "keywords"; private final JabRefFrame frame; @@ -280,10 +282,10 @@ public void actionPerformed(ActionEvent e) { Set userSelectedKeywords = new HashSet<>(); // build keywordsToAdd and userSelectedKeywords in parallel for (Enumeration keywords = keywordListModel.elements(); keywords.hasMoreElements();) { - String kword = keywords.nextElement(); - userSelectedKeywords.add(kword); - if (!sortedKeywordsOfAllEntriesBeforeUpdateByUser.contains(kword)) { - keywordsToAdd.add(kword); + String keyword = keywords.nextElement(); + userSelectedKeywords.add(keyword); + if (!sortedKeywordsOfAllEntriesBeforeUpdateByUser.contains(keyword)) { + keywordsToAdd.add(keyword); } } @@ -312,26 +314,16 @@ private NamedCompound updateKeywords(List entries, Set keyword Set keywordsToRemove) { NamedCompound ce = new NamedCompound(Localization.lang("Update keywords")); for (BibEntry entry : entries) { - List separatedKeywords = entry.getSeparatedKeywords(); - - // we "intercept" with a TreeSet - // pro: no duplicates - // possible con: alphabetical sorting of the keywords - Set keywords = new TreeSet<>(); - keywords.addAll(separatedKeywords); + Set keywords = entry.getKeywords(); // update keywords keywords.removeAll(keywordsToRemove); keywords.addAll(keywordsToAdd); // put keywords back - separatedKeywords.clear(); - separatedKeywords.addAll(keywords); - String oldValue = entry.getField(KEYWORDS_FIELD); - entry.putKeywords(separatedKeywords); - String updatedValue = entry.getField(KEYWORDS_FIELD); - if (!Objects.equals(oldValue, updatedValue)) { - ce.addEdit(new UndoableFieldChange(entry, KEYWORDS_FIELD, oldValue, updatedValue)); + Optional change = entry.putKeywords(keywords); + if (change.isPresent()) { + ce.addEdit(new UndoableFieldChange(change.get())); } if (SpecialFieldsUtils.keywordSyncEnabled()) { @@ -407,7 +399,7 @@ private void fillKeyWordList() { if (mergeKeywords.isSelected()) { for (BibEntry entry : entries) { - List separatedKeywords = entry.getSeparatedKeywords(); + Set separatedKeywords = entry.getKeywords(); sortedKeywordsOfAllEntriesBeforeUpdateByUser.addAll(separatedKeywords); } } else { @@ -415,14 +407,14 @@ private void fillKeyWordList() { // all keywords from first entry have to be added BibEntry firstEntry = entries.get(0); - List separatedKeywords = firstEntry.getSeparatedKeywords(); + Set separatedKeywords = firstEntry.getKeywords(); sortedKeywordsOfAllEntriesBeforeUpdateByUser.addAll(separatedKeywords); // for the remaining entries, intersection has to be used // this approach ensures that one empty keyword list leads to an empty set of common keywords for (int i = 1; i < entries.size(); i++) { BibEntry entry = entries.get(i); - separatedKeywords = entry.getSeparatedKeywords(); + separatedKeywords = entry.getKeywords(); sortedKeywordsOfAllEntriesBeforeUpdateByUser.retainAll(separatedKeywords); } } diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index e9320e219f15..a0b3471a60a4 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -269,7 +269,8 @@ public void stateChanged(ChangeEvent e) { showOverlappingGroups.addActionListener(e -> valueChanged(null)); autoGroup.addActionListener(e -> { AutoGroupDialog gd = new AutoGroupDialog(frame, panel, groupsRoot, - Globals.prefs.get(JabRefPreferences.GROUPS_DEFAULT_FIELD), " .,", ","); + Globals.prefs.get(JabRefPreferences.GROUPS_DEFAULT_FIELD), " .,", + Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); gd.setVisible(true); // gd does the operation itself }); diff --git a/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java b/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java index 0042a200a944..f2fdfb6a1002 100644 --- a/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java +++ b/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java @@ -19,7 +19,7 @@ import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableFieldChange; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.l10n.Localization; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java index 83e8f3f899c7..73024114d120 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java @@ -127,7 +127,7 @@ public void setValues() { groupingField.setText(prefs.get(JabRefPreferences.GROUPS_DEFAULT_FIELD)); autoShow.setSelected(prefs.getBoolean(JabRefPreferences.GROUP_AUTO_SHOW)); autoHide.setSelected(prefs.getBoolean(JabRefPreferences.GROUP_AUTO_HIDE)); - keywordSeparator.setText(prefs.get(JabRefPreferences.GROUP_KEYWORD_SEPARATOR)); + keywordSeparator.setText(prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); autoAssignGroup.setSelected(prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); } @@ -140,7 +140,7 @@ public void storeSettings() { prefs.putBoolean(JabRefPreferences.GROUP_AUTO_SHOW, autoShow.isSelected()); prefs.putBoolean(JabRefPreferences.GROUP_AUTO_HIDE, autoHide.isSelected()); prefs.putBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP, autoAssignGroup.isSelected()); - prefs.put(JabRefPreferences.GROUP_KEYWORD_SEPARATOR, keywordSeparator.getText()); + prefs.put(JabRefPreferences.KEYWORD_SEPARATOR, keywordSeparator.getText()); } @Override diff --git a/src/main/java/net/sf/jabref/gui/undo/UndoableFieldChange.java b/src/main/java/net/sf/jabref/gui/undo/UndoableFieldChange.java index ced72411df2b..a4f6663a6243 100644 --- a/src/main/java/net/sf/jabref/gui/undo/UndoableFieldChange.java +++ b/src/main/java/net/sf/jabref/gui/undo/UndoableFieldChange.java @@ -17,8 +17,8 @@ import javax.swing.undo.AbstractUndoableEdit; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index ca847f1250dd..2ff15326bd6d 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -521,7 +521,7 @@ private BibEntry cleanup(BibEntry entry) { // Replace ; as keyword separator entry.getFieldOptional("keywords").ifPresent(keys -> entry.setField("keywords", - keys.replace(";", Globals.prefs.get(JabRefPreferences.GROUP_KEYWORD_SEPARATOR)))); + keys.replace(";", Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)))); return entry; } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java index 0f1ea4daaee1..b8c1afc2f1ae 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java @@ -17,6 +17,7 @@ package net.sf.jabref.importer.fileformat; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; import net.sf.jabref.model.entry.BibEntry; @@ -104,7 +105,7 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { // Keywords if (bibJsonEntry.has("keywords")) { JSONArray keywords = bibJsonEntry.getJSONArray("keywords"); - List keywordList = new ArrayList<>(); + LinkedHashSet keywordList = new LinkedHashSet<>(); for (int i = 0; i < keywords.length(); i++) { if (!keywords.isNull(i)) { keywordList.add(keywords.getString(i)); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index a1af94056800..d74ed3dfc018 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; +import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; @@ -349,7 +350,7 @@ private void parseAdditionalFields(BibEntry be, boolean multilineUrlFieldAllowed if ("Keywords".equals(keyword)) { String content = readMultipleLines(in); String[] keywords = content.split("[,;]"); - be.addKeywords(Arrays.asList(keywords)); + be.addKeywords(new LinkedHashSet<>(Arrays.asList(keywords))); // parse JEL field } else if ("JEL".equals(keyword)) { be.setField("jel", readMultipleLines(in)); diff --git a/src/main/java/net/sf/jabref/logic/TypedBibEntry.java b/src/main/java/net/sf/jabref/logic/TypedBibEntry.java index 080c06f2f3c9..b3bc4898d30f 100644 --- a/src/main/java/net/sf/jabref/logic/TypedBibEntry.java +++ b/src/main/java/net/sf/jabref/logic/TypedBibEntry.java @@ -23,6 +23,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.model.EntryTypes; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java index 295057ae67e0..3de5e4bd51d9 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java @@ -18,7 +18,7 @@ import java.util.List; import java.util.Map; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryConverter; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupJob.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupJob.java index 252b3aa7b2a7..854d3d1ef90b 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupJob.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupJob.java @@ -16,7 +16,7 @@ import java.util.List; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; @FunctionalInterface @@ -27,4 +27,4 @@ public interface CleanupJob { */ List cleanup(BibEntry entry); -} \ No newline at end of file +} diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java index db57726272dc..8c6c8edee187 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java @@ -20,8 +20,8 @@ import java.util.Objects; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; public class CleanupWorker { 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 6478850234be..c920b1b11fd2 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java @@ -18,9 +18,9 @@ import java.util.List; import java.util.Optional; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.formatter.bibtexfields.ClearFormatter; import net.sf.jabref.logic.util.DOI; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; /** 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 6199764cbbbb..a4c54ec32933 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java @@ -20,8 +20,8 @@ import java.util.Locale; import java.util.Objects; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.formatter.Formatter; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; /** diff --git a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java index 773af79878d7..0de9c7440d2a 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java @@ -18,7 +18,7 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java index 9ff8cb2719ca..1713c5c7dde8 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/MoveFilesCleanup.java @@ -21,9 +21,9 @@ import java.util.Optional; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.TypedBibEntry; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.ParsedFileField; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java index 5e5de2c9db1a..a8ca97494dd5 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java @@ -21,9 +21,9 @@ import java.util.Optional; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.TypedBibEntry; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.ParsedFileField; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java index 19d70a8879fb..534824abb78d 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java @@ -21,10 +21,10 @@ import java.util.Optional; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.TypedBibEntry; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.ParsedFileField; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java index 341209aa8141..c561807323c0 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java @@ -21,7 +21,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.external.ExternalFileTypes; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; diff --git a/src/main/java/net/sf/jabref/logic/groups/EntriesGroupChange.java b/src/main/java/net/sf/jabref/logic/groups/EntriesGroupChange.java index d94c4d4c38da..f9d1f68a1ff7 100644 --- a/src/main/java/net/sf/jabref/logic/groups/EntriesGroupChange.java +++ b/src/main/java/net/sf/jabref/logic/groups/EntriesGroupChange.java @@ -19,7 +19,7 @@ import java.util.List; import java.util.Set; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; public class EntriesGroupChange { diff --git a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java index 6db7a6d49845..6b8beb616dbe 100644 --- a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java @@ -24,10 +24,10 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.ParseException; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.strings.QuotedStringTokenizer; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import org.apache.commons.logging.Log; @@ -136,7 +136,7 @@ public Optional add(List entriesToAdd) { if (!contains(entry)) { String oldContent = entry .getField(searchField); - String pre = Globals.prefs.get(JabRefPreferences.GROUP_KEYWORD_SEPARATOR); + String pre = Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR); String newContent = (oldContent == null ? "" : oldContent + pre) + searchExpression; @@ -254,7 +254,7 @@ private void removeMatches(BibEntry entry) { int i; int j; int k; - final String separator = Globals.prefs.get(JabRefPreferences.GROUP_KEYWORD_SEPARATOR); + final String separator = Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR); while ((i = haystack.indexOf(needle)) >= 0) { sbOrig.replace(i, i + needle.length(), ""); sbLower.replace(i, i + needle.length(), ""); diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index 14659ad66ac7..7c15e9f86fb7 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -758,13 +759,13 @@ else if (val.matches("edtr\\d+")) { } else if (val.matches("keyword\\d+")) { // according to LabelPattern.php, it returns keyword number n int num = Integer.parseInt(val.substring(7)); - List separatedKeywords = entry.getSeparatedKeywords(); + Set separatedKeywords = entry.getKeywords(); if (separatedKeywords.size() < num) { // not enough keywords return ""; } else { // num counts from 1 to n, but index in arrayList count from 0 to n-1 - return separatedKeywords.get(num-1); + return new ArrayList<>(separatedKeywords).get(num-1); } } else if (val.matches("keywords\\d*")) { // return all keywords, not separated @@ -774,13 +775,18 @@ else if (val.matches("edtr\\d+")) { } else { num = Integer.MAX_VALUE; } - List separatedKeywords = entry.getSeparatedKeywords(); + Set separatedKeywords = entry.getKeywords(); StringBuilder sb = new StringBuilder(); - for (int i = 0; i < Math.min(separatedKeywords.size(), num); i++) { - String keyword = separatedKeywords.get(i); + int i = 0; + for (String keyword : separatedKeywords) { // remove all spaces keyword = keyword.replaceAll("\\s+", ""); sb.append(keyword); + + i++; + if (i >= num) { + break; + } } return sb.toString(); } else { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/RisKeywords.java b/src/main/java/net/sf/jabref/logic/layout/format/RisKeywords.java index 292641c1e6e6..68c43f576efe 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/RisKeywords.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/RisKeywords.java @@ -15,7 +15,7 @@ */ package net.sf.jabref.logic.layout.format; -import java.util.List; +import java.util.Set; import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.LayoutFormatter; @@ -28,13 +28,15 @@ public String format(String s) { return ""; } StringBuilder sb = new StringBuilder(); - List keywords = net.sf.jabref.model.entry.EntryUtil.getSeparatedKeywords(s); - for (int i = 0; i < keywords.size(); i++) { + Set keywords = net.sf.jabref.model.entry.EntryUtil.getSeparatedKeywords(s); + int i = 0; + for (String keyword : keywords) { sb.append("KW - "); - sb.append(keywords.get(i)); + sb.append(keyword); if (i < (keywords.size() - 1)) { sb.append(Globals.NEWLINE); } + i++; } return sb.toString(); } diff --git a/src/main/java/net/sf/jabref/logic/util/UpdateField.java b/src/main/java/net/sf/jabref/logic/util/UpdateField.java index 691842707d02..8aa804559c92 100644 --- a/src/main/java/net/sf/jabref/logic/util/UpdateField.java +++ b/src/main/java/net/sf/jabref/logic/util/UpdateField.java @@ -5,8 +5,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.util.date.EasyDateFormat; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; diff --git a/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java b/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java index 8a9cb77da760..9f6ff9338d72 100644 --- a/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java +++ b/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java @@ -4,8 +4,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.logic.FieldChange; import net.sf.jabref.logic.util.UpdateField; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; public class TimeStamp { diff --git a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java index 55e03ec6868d..031c26914550 100644 --- a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java +++ b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java @@ -34,9 +34,9 @@ import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.PostOpenAction; -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.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/logic/FieldChange.java b/src/main/java/net/sf/jabref/model/FieldChange.java similarity index 73% rename from src/main/java/net/sf/jabref/logic/FieldChange.java rename to src/main/java/net/sf/jabref/model/FieldChange.java index a2389e96a501..b77c3807797b 100644 --- a/src/main/java/net/sf/jabref/logic/FieldChange.java +++ b/src/main/java/net/sf/jabref/model/FieldChange.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic; +/* + * Copyright (C) 2003-2016 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.model; import java.util.Objects; diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 9bfc08973457..16a3266d6c55 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -32,7 +32,10 @@ import java.util.Set; import java.util.TreeSet; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.event.FieldChangedEvent; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import com.google.common.base.Strings; @@ -46,6 +49,7 @@ public class BibEntry implements Cloneable { public static final String TYPE_HEADER = "entrytype"; public static final String KEY_FIELD = "bibtexkey"; protected static final String ID_FIELD = "id"; + public static final String KEYWORDS_FIELD = "keywords"; public static final String DEFAULT_TYPE = "misc"; private String id; @@ -334,20 +338,23 @@ public void setField(Map fields) { /** * Set a field, and notify listeners about the change. - * - * @param name The field to set. + * @param name The field to set. * @param value The value to set. */ - public void setField(String name, String value) { + public Optional setField(String name, String value) { Objects.requireNonNull(name, "field name must not be null"); Objects.requireNonNull(value, "field value must not be null"); + String fieldName = toLowerCase(name); + if (value.isEmpty()) { - clearField(name); - return; + return clearField(fieldName); } - String fieldName = toLowerCase(name); + String oldValue = getField(fieldName); + if (value.equals(oldValue)) { + return Optional.empty(); + } if (BibEntry.ID_FIELD.equals(fieldName)) { throw new IllegalArgumentException("The field name '" + name + "' is reserved"); @@ -356,7 +363,10 @@ public void setField(String name, String value) { changed = true; fields.put(fieldName, value); - eventBus.post(new FieldChangedEvent(this, fieldName, value)); + + FieldChange change = new FieldChange(this, fieldName, oldValue, value); + eventBus.post(new FieldChangedEvent(change)); + return Optional.of(change); } /** @@ -365,16 +375,24 @@ public void setField(String name, String value) { * * @param name The field to clear. */ - public void clearField(String name) { + public Optional clearField(String name) { String fieldName = toLowerCase(name); - changed = true; - if (BibEntry.ID_FIELD.equals(fieldName)) { throw new IllegalArgumentException("The field name '" + name + "' is reserved"); } + + Optional oldValue = getFieldOptional(fieldName); + if (!oldValue.isPresent()) { + return Optional.empty(); + } + + changed = true; + fields.remove(fieldName); - eventBus.post(new FieldChangedEvent(this, fieldName, null)); + FieldChange change = new FieldChange(this, fieldName, oldValue.get(), null); + eventBus.post(new FieldChangedEvent(change)); + return Optional.of(change); } /** @@ -513,25 +531,22 @@ public void setChanged(boolean changed) { this.changed = changed; } - public void putKeywords(List keywords) { + public Optional putKeywords(Collection keywords) { Objects.requireNonNull(keywords); - // Set Keyword Field - String oldValue = this.getField("keywords"); - String newValue; + Optional oldValue = this.getFieldOptional(KEYWORDS_FIELD); + if (keywords.isEmpty()) { - newValue = null; - } else { - newValue = String.join(", ", keywords); - } - if (newValue == null) { - if (oldValue != null) { - this.clearField("keywords"); + // Clear keyword field + if (oldValue.isPresent()) { + return this.clearField(KEYWORDS_FIELD); + } else { + return Optional.empty(); } - return; - } - if (!Objects.equals(oldValue, newValue)) { - this.setField("keywords", newValue); } + + // Set new keyword field + String newValue = String.join(Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR), keywords); + return this.setField(KEYWORDS_FIELD, newValue); } /** @@ -540,26 +555,15 @@ public void putKeywords(List keywords) { * @param keyword Keyword to add */ public void addKeyword(String keyword) { - Objects.requireNonNull(keyword, "keyword must not be empty"); + Objects.requireNonNull(keyword, "keyword must not be null"); if (keyword.isEmpty()) { return; } - List keywords = this.getSeparatedKeywords(); - Boolean duplicate = false; - - for (String key : keywords) { - if (keyword.equalsIgnoreCase(key)) { - duplicate = true; - break; - } - } - - if (!duplicate) { - keywords.add(keyword); - this.putKeywords(keywords); - } + Set keywords = this.getKeywords(); + keywords.add(keyword); + this.putKeywords(keywords); } /** @@ -567,7 +571,7 @@ public void addKeyword(String keyword) { * * @param keywords Keywords to add */ - public void addKeywords(List keywords) { + public void addKeywords(Collection keywords) { Objects.requireNonNull(keywords); for (String keyword : keywords) { @@ -575,8 +579,8 @@ public void addKeywords(List keywords) { } } - public List getSeparatedKeywords() { - return net.sf.jabref.model.entry.EntryUtil.getSeparatedKeywords(this.getField("keywords")); + public Set getKeywords() { + return net.sf.jabref.model.entry.EntryUtil.getSeparatedKeywords(this.getField(KEYWORDS_FIELD)); } public Collection getFieldValues() { diff --git a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java index 3f1bf760ae2b..3f50d01844c2 100644 --- a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java +++ b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java @@ -1,7 +1,7 @@ package net.sf.jabref.model.entry; -import java.util.ArrayList; -import java.util.List; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.StringTokenizer; public class EntryUtil { @@ -24,23 +24,23 @@ public static String capitalizeFirst(String toCapitalize) { } /** - * @param keywords a String of keywords + * @param keywordString a String of keywords * @return an List containing the keywords. An empty list if keywords are null or empty */ - public static List getSeparatedKeywords(String keywords) { - List res = new ArrayList<>(); - if (keywords == null) { - return res; + public static Set getSeparatedKeywords(String keywordString) { + LinkedHashSet keywords = new LinkedHashSet<>(); + if (keywordString == null) { + return keywords; } // _NOSPACE is a hack to support keywords such as "choreography transactions" // a more intelligent algorithm would check for the separator chosen (SEPARATING_CHARS_NOSPACE) // if nothing is found, " " is likely to be the separating char. // solution by RisKeywords.java: s.split(",[ ]*") - StringTokenizer tok = new StringTokenizer(keywords, SEPARATING_CHARS_NOSPACE); + StringTokenizer tok = new StringTokenizer(keywordString, SEPARATING_CHARS_NOSPACE); while (tok.hasMoreTokens()) { String word = tok.nextToken().trim(); - res.add(word); + keywords.add(word); } - return res; + return keywords; } } diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java index 9867873ff908..9ad407f5f82f 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java @@ -15,18 +15,22 @@ */ package net.sf.jabref.specialfields; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; +import java.util.Set; import net.sf.jabref.Globals; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.logic.util.UpdateField; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import static net.sf.jabref.model.entry.BibEntry.KEYWORDS_FIELD; + public class SpecialFieldsUtils { - private static final String KEYWORDS_FIELD = "keywords"; public static final String FIELDNAME_PRIORITY = "priority"; public static final String FIELDNAME_RANKING = "ranking"; public static final String FIELDNAME_RELEVANCE = "relevance"; @@ -88,17 +92,17 @@ private static void exportFieldToKeywords(SpecialField e, BibEntry be, NamedComp SpecialFieldsUtils.exportFieldToKeywords(e, be.getField(e.getFieldName()), be, ce); } - private static void exportFieldToKeywords(SpecialField e, String newValue, BibEntry be, NamedCompound ce) { + private static void exportFieldToKeywords(SpecialField e, String newValue, BibEntry entry, NamedCompound ce) { if (!SpecialFieldsUtils.keywordSyncEnabled()) { return; } - List keywordList = be.getSeparatedKeywords(); - List values = e.getKeyWords(); + List keywordList = new ArrayList<>(entry.getKeywords()); + List specialFieldsKeywords = e.getKeyWords(); int foundPos = -1; // cleanup keywords - for (Object value : values) { + for (Object value : specialFieldsKeywords) { int pos = keywordList.indexOf(value); if (pos >= 0) { foundPos = pos; @@ -113,13 +117,12 @@ private static void exportFieldToKeywords(SpecialField e, String newValue, BibEn keywordList.add(foundPos, newValue); } } - String oldValue = be.getField(KEYWORDS_FIELD); - be.putKeywords(keywordList); - String updatedValue = be.getField(KEYWORDS_FIELD); - if ((!Objects.equals(oldValue, updatedValue)) && (ce != null)) { - ce.addEdit(new UndoableFieldChange(be, KEYWORDS_FIELD, oldValue, updatedValue)); - } + + Optional change = entry.putKeywords(keywordList); + if (ce != null && change.isPresent()) { + ce.addEdit(new UndoableFieldChange(change.get())); + } } /** @@ -136,7 +139,7 @@ public static void syncKeywordsFromSpecialFields(BibEntry be, NamedCompound nc) SpecialFieldsUtils.exportFieldToKeywords(Printed.getInstance(), be, nc); } - private static void importKeywordsForField(List keywordList, SpecialField c, BibEntry be, + private static void importKeywordsForField(Set keywordList, SpecialField c, BibEntry be, NamedCompound nc) { List values = c.getKeyWords(); String newValue = null; @@ -159,7 +162,7 @@ public static void syncSpecialFieldsFromKeywords(BibEntry be, NamedCompound ce) if (!be.hasField(KEYWORDS_FIELD)) { return; } - List keywordList = net.sf.jabref.model.entry.EntryUtil + Set keywordList = net.sf.jabref.model.entry.EntryUtil .getSeparatedKeywords(be.getField(KEYWORDS_FIELD)); SpecialFieldsUtils.importKeywordsForField(keywordList, Priority.getInstance(), be, ce); SpecialFieldsUtils.importKeywordsForField(keywordList, Rank.getInstance(), be, ce); diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index b8e547734ea2..c68aeb1bb609 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -12,7 +12,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.exporter.FieldFormatterCleanups; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; diff --git a/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java b/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java index d11124fa0521..86a1f1bd26f7 100644 --- a/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java +++ b/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java @@ -2,7 +2,7 @@ import java.util.Optional; -import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java similarity index 82% rename from src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java rename to src/test/java/net/sf/jabref/model/entry/BibEntryTests.java index a6ecfb3e2179..e1826638860f 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java @@ -5,16 +5,18 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.model.FieldChange; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -public class BibtexEntryTests { +public class BibEntryTests { private BibEntry keywordEntry; private BibEntry emptyEntry; @@ -222,14 +224,14 @@ public void putNullKeywordListThrowsNPE() { @Test public void testGetSeparatedKeywordsAreCorrect() { String[] expected = {"Foo", "Bar"}; - Assert.assertArrayEquals(expected, keywordEntry.getSeparatedKeywords().toArray()); + Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test public void testAddKeywordIsCorrect() { keywordEntry.addKeyword("FooBar"); String[] expected = {"Foo", "Bar", "FooBar"}; - Assert.assertArrayEquals(expected, keywordEntry.getSeparatedKeywords().toArray()); + Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test @@ -243,27 +245,27 @@ public void testAddKeywordTwiceYiedsOnlyOne() { keywordEntry.addKeyword("FooBar"); keywordEntry.addKeyword("FooBar"); String[] expected = {"Foo", "Bar", "FooBar"}; - Assert.assertArrayEquals(expected, keywordEntry.getSeparatedKeywords().toArray()); + Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test - public void testAddKeywordIsCaseInsensitive() { + public void addKeywordIsCaseSensitive() { keywordEntry.addKeyword("FOO"); - String[] expected = {"Foo", "Bar"}; - Assert.assertArrayEquals(expected, keywordEntry.getSeparatedKeywords().toArray()); + String[] expected = {"Foo", "Bar", "FOO"}; + Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test - public void testAddSameKeywordNotChanged() { + public void testAddKeywordWithDifferentCapitalizationChanges() { keywordEntry.addKeyword("FOO"); - Assert.assertFalse(keywordEntry.hasChanged()); + Assert.assertTrue(keywordEntry.hasChanged()); } @Test public void testAddKeywordEmptyKeywordIsNotAdded() { keywordEntry.addKeyword(""); String[] expected = {"Foo", "Bar"}; - Assert.assertArrayEquals(expected, keywordEntry.getSeparatedKeywords().toArray()); + Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test @@ -274,13 +276,13 @@ public void testAddKeywordEmptyKeywordNotChanged() { @Test public void texNewBibEntryHasNoKeywords() { - Assert.assertTrue(emptyEntry.getSeparatedKeywords().isEmpty()); + Assert.assertTrue(emptyEntry.getKeywords().isEmpty()); } @Test public void texNewBibEntryHasNoKeywordsEvenAfterAddingEmptyKeyword() { emptyEntry.addKeyword(""); - Assert.assertTrue(emptyEntry.getSeparatedKeywords().isEmpty()); + Assert.assertTrue(emptyEntry.getKeywords().isEmpty()); } @Test @@ -292,15 +294,15 @@ public void texNewBibEntryAfterAddingEmptyKeywordNotChanged() { @Test public void testAddKeywordsWorksAsExpected() { String[] expected = {"Foo", "Bar"}; - emptyEntry.addKeywords(keywordEntry.getSeparatedKeywords()); - Assert.assertArrayEquals(expected, emptyEntry.getSeparatedKeywords().toArray()); + emptyEntry.addKeywords(keywordEntry.getKeywords()); + Assert.assertArrayEquals(expected, emptyEntry.getKeywords().toArray()); } @Test public void testPutKeywordsOverwritesOldKeywords() { keywordEntry.putKeywords(Arrays.asList("Yin", "Yang")); String[] expected = {"Yin", "Yang"}; - Assert.assertArrayEquals(expected, keywordEntry.getSeparatedKeywords().toArray()); + Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test @@ -312,7 +314,7 @@ public void testPutKeywordsHasChanged() { @Test public void testPutKeywordsPutEmpyListErasesPreviousKeywords() { keywordEntry.putKeywords(Collections.emptyList()); - Assert.assertTrue(keywordEntry.getSeparatedKeywords().isEmpty()); + Assert.assertTrue(keywordEntry.getKeywords().isEmpty()); } @Test @@ -324,7 +326,7 @@ public void testPutKeywordsPutEmpyListHasChanged() { @Test public void testPutKeywordsPutEmpyListToEmptyBibentry() { emptyEntry.putKeywords(Collections.emptyList()); - Assert.assertTrue(emptyEntry.getSeparatedKeywords().isEmpty()); + Assert.assertTrue(emptyEntry.getKeywords().isEmpty()); } @Test @@ -333,6 +335,30 @@ public void testPutKeywordsPutEmpyListToEmptyBibentryNotChanged() { Assert.assertFalse(emptyEntry.hasChanged()); } + @Test + public void putKeywordsToEmptyReturnsNoChange() { + Optional change = emptyEntry.putKeywords(Collections.emptyList()); + Assert.assertEquals(Optional.empty(), change); + } + + @Test + public void clearKeywordsReturnsChange() { + Optional change = keywordEntry.putKeywords(Collections.emptyList()); + Assert.assertEquals(Optional.of(new FieldChange(keywordEntry, "keywords", "Foo, Bar", null)), change); + } + + @Test + public void changeKeywordsReturnsChange() { + Optional change = keywordEntry.putKeywords(Arrays.asList("Test", "FooTest")); + Assert.assertEquals(Optional.of(new FieldChange(keywordEntry, "keywords", "Foo, Bar", "Test, FooTest")), change); + } + + @Test + public void putKeywordsToSameReturnsNoChange() { + Optional change = keywordEntry.putKeywords(Arrays.asList("Foo", "Bar")); + Assert.assertEquals(Optional.empty(), change); + } + @Test public void testGroupAndSearchHits() { BibEntry be = new BibEntry(); diff --git a/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java b/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java index b306f69f5e28..7064c839d447 100644 --- a/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java +++ b/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java @@ -1,6 +1,8 @@ package net.sf.jabref.model.entry; -import java.util.List; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; import org.junit.Assert; import org.junit.Test; @@ -18,9 +20,8 @@ public void testNCase() { @Test public void getSeparatedKeywords() { String keywords = "w1, w2a w2b, w3"; - List separatedKeywords = EntryUtil.getSeparatedKeywords(keywords); - String[] expected = new String[] {"w1", "w2a w2b", "w3"}; - Assert.assertArrayEquals(expected, separatedKeywords.toArray()); + Set separatedKeywords = EntryUtil.getSeparatedKeywords(keywords); + Assert.assertEquals(new LinkedHashSet<>(Arrays.asList("w1", "w2a w2b", "w3")), separatedKeywords); } From b77975d276bfc673ade84520535e289ffd6b381a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 27 Jun 2016 21:33:25 +0200 Subject: [PATCH 164/268] Move start of xvfb to script part to avoid high memory consumption during normal check routine --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 135d97810f1c..456b340d9098 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,16 +12,16 @@ install: true # allow gui testing on travis before_script: - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - sleep 3 # give xvfb some time to start - psql -c 'create database jabref;' -U postgres script: - ./gradlew check # Integration tests currently often fail with "Process 'Gradle Test Executor 1' finished with non-zero exit value 137" # They should run, but the result is ignored - - ./gradlew integrationTest --info || exit 0 + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - sleep 3 # give xvfb some time to start + - ./gradlew integrationTest --info || true after_script: # enable codecov report From e7455ee07956ae7f2646db489e89d30d535c3f3e Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 27 Jun 2016 23:33:24 +0200 Subject: [PATCH 165/268] Switch to Ubuntu 14.04 LTS and reduce memory consumption at integrationTest --- .travis.yml | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 456b340d9098..fd3b82f02762 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,20 @@ language: java -jdk: - - oraclejdk8 -sudo: false + +# we test at Ubuntu Trusty (Ubuntu 14.04 LTS) +# see https://docs.travis-ci.com/user/trusty-ci-environment/ +sudo: required +dist: trusty + +# update to latest Java8 as described at https://github.com/travis-ci/travis-ci/issues/4042#issuecomment-109756980 +addons: + apt: + packages: + # most recent Java8 - this makes the DK switcher obsolete - see https://github.com/travis-ci/travis-ci/issues/5897#issuecomment-218354129 + - oracle-java8-installer + # MySQL 5.6 as desccribed at https://docs.travis-ci.com/user/database-setup/#MySQL-5.6 + - mysql-server-5.6 + - mysql-client-core-5.6 + - mysql-client-5.6 services: - postgresql @@ -21,6 +34,20 @@ script: - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" - sleep 3 # give xvfb some time to start + # no need for databases for the integrationTest -> save memory + - sudo service mysql stop + - sudo service postgresql stop + # following services identified by "sudo service --status-all" do not need to run, too + # excluded: rsyslog (feels wrong), udev (feels wrong), friendly-recovery ("Unkonwn instance" error) + - sudo service acpid stop + - sudo service atd stop + - sudo service cron stop + - sudo service memcached stop + - sudo service ntp stop + - sudo service rabbitmq-server stop + - sudo service resolvconf stop + - sudo service sshguard stop + - sudo service ssh stop - ./gradlew integrationTest --info || true after_script: From f01b364a80e6ed6402c61e932b51264e5071c36c Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 28 Jun 2016 19:26:04 +0200 Subject: [PATCH 166/268] Fix order of imports --- .../net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java b/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java index f2fdfb6a1002..6023530d1f27 100644 --- a/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java +++ b/src/main/java/net/sf/jabref/gui/groups/UndoableChangeEntriesOfGroup.java @@ -19,9 +19,9 @@ import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableFieldChange; -import net.sf.jabref.model.FieldChange; import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.FieldChange; public class UndoableChangeEntriesOfGroup { From 37f279f308f2784a95e3744321eb4049218fd1b8 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 28 Jun 2016 19:30:40 +0200 Subject: [PATCH 167/268] Fix import order --- .../java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index c68aeb1bb609..25a6eed16a49 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -12,7 +12,6 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.exporter.FieldFormatterCleanups; -import net.sf.jabref.model.FieldChange; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; @@ -21,6 +20,7 @@ import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FileField; From 12ae6e35d355e295f8e7e2a4d6a9c71f0f9a5654 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 28 Jun 2016 20:29:52 +0200 Subject: [PATCH 168/268] Use Objects.requireNonNull --- .../java/net/sf/jabref/model/database/BibDatabase.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index e804bd58cb1c..ae3987e9c767 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -347,9 +347,7 @@ public synchronized boolean hasStringLabel(String label) { * if possible. */ public String resolveForStrings(String content) { - if (content == null) { - throw new IllegalArgumentException("Content for resolveForStrings must not be null."); - } + Objects.requireNonNull(content, "Content for resolveForStrings must not be null."); return resolveContent(content, new HashSet<>()); } @@ -364,9 +362,7 @@ public String resolveForStrings(String content) { * @return a list of bibtexentries, with all strings resolved. It is dependent on the value of inPlace whether copies are made or the given BibtexEntries are modified. */ public List resolveForStrings(Collection entries, boolean inPlace) { - if (entries == null) { - throw new IllegalArgumentException("entries must not be null"); - } + Objects.requireNonNull(entries, "entries must not be null."); List results = new ArrayList<>(entries.size()); From eba0b6e8ebc7f01e66a2a8962a23d8d3a9e583b7 Mon Sep 17 00:00:00 2001 From: MLEP Date: Wed, 29 Jun 2016 17:40:49 +0200 Subject: [PATCH 169/268] French localization: translation of empty strings; correction of a few glitches --- src/main/resources/l10n/JabRef_fr.properties | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 844be8865692..d858300eb70d 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -519,7 +519,7 @@ Password=Mot_de_passe Paste=Coller paste_entries=Coller_les_entrées paste_entry=Coller_l'entrée -Paste_from_clipboard=Coller_depuis_le_presse-papier +Paste_from_clipboard=Coller_depuis_le_presse-papiers Pasted=Collé Path_to_%0_not_defined=Chemin_vers_%0_non_défini Path_to_LyX_pipe=Chemin_du_canal_de_transmission_LyX @@ -1616,8 +1616,8 @@ incorrect_format=format_incorrect Expected_"%0"_to_contain_whitespace="%0"_devrait_contenir_une_espace Syntax_error_in_regular-expression_pattern=Erreur_de_syntaxe_dans_le_format_d'une_expression_régulière -Copy_version_to_clipboard=Copier_la_version_dans_le_presse-papier -Copied_version_to_clipboard=Version_copiée_dans_le_presse-papier +Copy_version_to_clipboard=Copier_la_version_dans_le_presse-papiers +Copied_version_to_clipboard=Version_copiée_dans_le_presse-papiers booktitle_ends_with_'conference_on'=le_titre_d'ouvrage_se_termine_par_'conference_on' BibTeX_key=Clef_BibTeX @@ -1633,19 +1633,19 @@ Cleared_'%0'_for_%1_entries=Réinitialisés_'%0'_pour_%1_entrées Set_'%0'_to_'%1'_for_%2_entries='%0'_mis_à_'%1'_pour_%2_entrées Toggled_'%0'_for_%1_entries='%0'_modifiée_pour_%1_entrées -Check_for_updates= -Download_update= -New_version_available= -Installed_version= -Remind_me_later= -Ignore_this_update= -Couldn't_connect_to_the_update_server.= -Please_try_again_later_and/or_check_your_network_connection.= -To_see_what's_new_view_the_changelog.= -A_new_version_of_JabRef_has_been_released.= -JabRef_is_up-to-date.= -Latest_version= - -Please_open_%0_manually.= - -The_link_has_been_copied_to_the_clipboard.= +Check_for_updates=Rechercher_des_mises_à_jour +Download_update=Télécharger_la_mise_à_jour +New_version_available=Nouvelle_version_disponible +Installed_version=Version_installée +Remind_me_later=Me_le_rappeler_plus_tard +Ignore_this_update=Ignorer_cette_mise_à_jour +Couldn't_connect_to_the_update_server.=La_connexion_au_serveur_de_mise_à_jour_a_échoué. +Please_try_again_later_and/or_check_your_network_connection.=Essayez_plus_tard_ou_vérifier_votre_connection_réseau. +To_see_what's_new_view_the_changelog.=Pour_voir_les_nouveautés,_affichez_le_journal_des_modifications. +A_new_version_of_JabRef_has_been_released.=Une_nouvelle_version_de_JabRef_a_été_publiée. +JabRef_is_up-to-date.=JabRef_est_à_jour. +Latest_version=Version_la_plus_récente + +Please_open_%0_manually.=Ouvrez_%0_manuellement,_SVP. + +The_link_has_been_copied_to_the_clipboard.=Le_lien_a_été_copié_dans_le_presse-papiers. From a4f79ad8c37a2cc669ad601b33df5416a7ad06bf Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 29 Jun 2016 22:51:35 +0200 Subject: [PATCH 170/268] Fix update notification for developer builds --- .../net/sf/jabref/logic/util/Version.java | 33 ++++++++++--------- .../logic/util/version/VersionTest.java | 14 ++++++++ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java index 7349c1f623c5..ce4c77bbccff 100644 --- a/src/main/java/net/sf/jabref/logic/util/Version.java +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -23,6 +23,8 @@ import java.util.Objects; import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.json.JSONObject; /** @@ -31,33 +33,34 @@ public class Version { public final static String JABREF_DOWNLOAD_URL = "http://www.fosshub.com/JabRef.html"; + private static final Log LOGGER = LogFactory.getLog(Version.class); private final static String JABREF_GITHUB_URL = "https://api.github.com/repos/JabRef/jabref/releases/latest"; - private final String fullVersion; - private final int major; - private final int minor; - private final int patch; - private final boolean isDevelopmentVersion; - + private String fullVersion = BuildInfo.UNKNOWN_VERSION; + private int major = 0; + private int minor = 0; + private int patch = 0; + private boolean isDevelopmentVersion = false; /** * @param version must be in form of X.X (eg 3.3; 3.4dev) */ public Version(String version) { if (version == null || "".equals(version) || version.equals(BuildInfo.UNKNOWN_VERSION)) { - this.fullVersion = BuildInfo.UNKNOWN_VERSION; - this.major = this.minor = this.patch = 0; - this.isDevelopmentVersion = false; return; } - this.fullVersion = version; - isDevelopmentVersion = version.contains("dev"); String[] versionParts = version.split("dev"); String[] versionNumbers = versionParts[0].split(Pattern.quote(".")); - this.major = Integer.parseInt(versionNumbers[0]); - this.minor = versionNumbers.length >= 2 ? Integer.parseInt(versionNumbers[1]) : 0; - this.patch = versionNumbers.length >= 3 ? Integer.parseInt(versionNumbers[2]) : 0; + try { + this.major = Integer.parseInt(versionNumbers[0]); + this.minor = versionNumbers.length >= 2 ? Integer.parseInt(versionNumbers[1]) : 0; + this.patch = versionNumbers.length >= 3 ? Integer.parseInt(versionNumbers[2]) : 0; + this.fullVersion = version; + this.isDevelopmentVersion = version.contains("dev"); + } catch (NumberFormatException exception) { + LOGGER.warn("Invalid version string used: " + version, exception); + } } /** @@ -86,7 +89,7 @@ public boolean isNewerThan(Version otherVersion) { return false; } if (otherVersion.getFullVersion().equals(BuildInfo.UNKNOWN_VERSION)) { - return true; + return false; } if (this.getMajor() > otherVersion.getMajor()) { diff --git a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java index 808c7429e6bb..c933aa816176 100644 --- a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java +++ b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java @@ -18,6 +18,12 @@ public void unknownVersion() { assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); } + @Test + public void initVersionFromWrongStringResultsInUnknownVersion() { + Version version = new Version("${version}"); + assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); + } + @Test public void versionOneDigit() { String versionText = "1"; @@ -84,6 +90,14 @@ public void versionThreeDigitDevVersion() { assertTrue(version.isDevelopmentVersion()); } + @Test + public void validVersionIsNotNewerThanUnknownVersion() { + // Reason: unknown version should only happen for developer builds where we don't want an update notification + Version unknownVersion = new Version(BuildInfo.UNKNOWN_VERSION); + Version validVersion = new Version("4.2"); + assertFalse(validVersion.isNewerThan(unknownVersion)); + } + @Test public void versionNewerThan() { Version olderVersion = new Version("2.4"); From dbc0ba65763384d37bd7e0c143ebf2bc67af5745 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 29 Jun 2016 19:51:26 +0200 Subject: [PATCH 171/268] More test cases (and apply agreed formatting rules) --- .../net/sf/jabref/logic/util/Version.java | 4 +- .../logic/util/version/VersionTest.java | 75 ++++++++++++++++++- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java index ce4c77bbccff..e13b18881956 100644 --- a/src/main/java/net/sf/jabref/logic/util/Version.java +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -46,7 +46,7 @@ public class Version { * @param version must be in form of X.X (eg 3.3; 3.4dev) */ public Version(String version) { - if (version == null || "".equals(version) || version.equals(BuildInfo.UNKNOWN_VERSION)) { + if ((version == null) || "".equals(version) || version.equals(BuildInfo.UNKNOWN_VERSION)) { return; } @@ -99,7 +99,7 @@ public boolean isNewerThan(Version otherVersion) { if (this.getMinor() > otherVersion.getMinor()) { return true; } - if (this.getMinor() == otherVersion.getMinor() && this.getPatch() > otherVersion.getPatch()) { + if ((this.getMinor() == otherVersion.getMinor()) && (this.getPatch() > otherVersion.getPatch())) { return true; } } diff --git a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java index c933aa816176..260a8e327985 100644 --- a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java +++ b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java @@ -13,8 +13,23 @@ public class VersionTest { @Test - public void unknownVersion() { - Version version = new Version(BuildInfo.UNKNOWN_VERSION); + public void unknownVersionAsString() { + String versionText = BuildInfo.UNKNOWN_VERSION; + Version version = new Version(versionText); + assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); + } + + @Test + public void unknownVersionAsNull() { + String versionText = null; + Version version = new Version(versionText); + assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); + } + + @Test + public void unknownVersionAsEmptyString() { + String versionText = ""; + Version version = new Version(versionText); assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); } @@ -105,6 +120,27 @@ public void versionNewerThan() { assertTrue(newerVersion.isNewerThan(olderVersion)); } + @Test + public void versionNotNewerThanSameVersion() { + Version version1 = new Version("4.2"); + Version version2 = new Version("4.2"); + assertFalse(version1.isNewerThan(version2)); + } + + @Test + public void concreteVersionNewerThanUnknownVersion() { + Version concreteVersion = new Version("4.2"); + Version unknownVersion = new Version(BuildInfo.UNKNOWN_VERSION); + assertTrue(concreteVersion.isNewerThan(unknownVersion)); + } + + @Test + public void unknownVersionNotNewerThanConceteVersion() { + Version concreteVersion = new Version("4.2"); + Version unknownVersion = new Version(BuildInfo.UNKNOWN_VERSION); + assertTrue(unknownVersion.isNewerThan(concreteVersion)); + } + @Test public void versionNewerThanDevTwoDigits() { Version older = new Version("4.2"); @@ -126,6 +162,20 @@ public void versionNewerPatch() { assertTrue(newer.isNewerThan(older)); } + @Test + public void versionNotNewerPatch() { + Version older = new Version("4.2.1"); + Version newer = new Version("4.2.2"); + assertFalse(older.isNewerThan(newer)); + } + + @Test + public void equalVersionsNotNewer() { + Version version1 = new Version("4.2.2"); + Version version2 = new Version("4.2.2"); + assertTrue(version1.isNewerThan(version2)); + } + @Test public void changelogWithTwoDigits(){ Version version = new Version("3.4"); @@ -138,4 +188,25 @@ public void changelogWithThreeDigits(){ assertEquals("https://github.com/JabRef/jabref/blob/v3.4.1/CHANGELOG.md", version.getChangelogUrl()); } + @Test + public void versionNotReplaced() { + String versionText = "${version}"; + Version version = new Version(versionText); + assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); + } + + @Test + public void versionNull() { + String versionText = null; + Version version = new Version(versionText); + assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); + } + + @Test + public void versionEmpty() { + String versionText = ""; + Version version = new Version(versionText); + assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); + } + } From bd9f43174a57b7adc3ed38b21cdfc09a22298a2a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 29 Jun 2016 22:39:50 +0200 Subject: [PATCH 172/268] Item 9 of Effective Java: Always override hashCode if you override equals --- src/main/java/net/sf/jabref/logic/util/Version.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java index e13b18881956..6dc31fd0a36e 100644 --- a/src/main/java/net/sf/jabref/logic/util/Version.java +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -150,8 +150,14 @@ public boolean equals(Object other) { return this.getFullVersion().equals(otherVersion.getFullVersion()); } + @Override + public int hashCode() { + return getFullVersion().hashCode(); + } + @Override public String toString() { return this.getFullVersion(); } + } From 550973a5cebbf65664ad03551e61394a8d9cbbcf Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 29 Jun 2016 22:40:13 +0200 Subject: [PATCH 173/268] Refine comments and use if/else if cascades to make code more readable --- .../net/sf/jabref/logic/util/Version.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java index 6dc31fd0a36e..31fcafd6ef30 100644 --- a/src/main/java/net/sf/jabref/logic/util/Version.java +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -43,7 +43,7 @@ public class Version { private boolean isDevelopmentVersion = false; /** - * @param version must be in form of X.X (eg 3.3; 3.4dev) + * @param version must be in form of X.X (e.g., 3.3; 3.4dev) */ public Version(String version) { if ((version == null) || "".equals(version) || version.equals(BuildInfo.UNKNOWN_VERSION)) { @@ -65,9 +65,6 @@ public Version(String version) { /** * Grabs the latest release version from the JabRef GitHub repository - * - * @return - * @throws IOException */ public static Version getLatestVersion() throws IOException { URLConnection connection = new URL(JABREF_GITHUB_URL).openConnection(); @@ -78,33 +75,29 @@ public static Version getLatestVersion() throws IOException { } /** - * @return true if this version is newer than the passed one + * @return true iff this version is newer than the passed one */ public boolean isNewerThan(Version otherVersion) { Objects.requireNonNull(otherVersion); if (Objects.equals(this, otherVersion)) { return false; - } - if (this.getFullVersion().equals(BuildInfo.UNKNOWN_VERSION)) { + } else if (this.getFullVersion().equals(BuildInfo.UNKNOWN_VERSION)) { return false; - } - if (otherVersion.getFullVersion().equals(BuildInfo.UNKNOWN_VERSION)) { + } else if (otherVersion.getFullVersion().equals(BuildInfo.UNKNOWN_VERSION)) { return false; - } - - if (this.getMajor() > otherVersion.getMajor()) { + } else if (this.getMajor() > otherVersion.getMajor()) { return true; - } - if (this.getMajor() == otherVersion.getMajor()) { + } else if (this.getMajor() == otherVersion.getMajor()) { if (this.getMinor() > otherVersion.getMinor()) { return true; - } - if ((this.getMinor() == otherVersion.getMinor()) && (this.getPatch() > otherVersion.getPatch())) { + } else if ((this.getMinor() == otherVersion.getMinor()) && (this.getPatch() > otherVersion.getPatch())) { return true; + } else { + return false; } + } else { + return false; } - - return false; } public String getFullVersion() { From 353494d855c124adee1b2e9e38861d107f72a58c Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Thu, 30 Jun 2016 08:15:07 +0200 Subject: [PATCH 174/268] Remove obsolete variables and tests; fix one test --- .../logic/util/version/VersionTest.java | 39 ++++++------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java index 260a8e327985..a7b4811b6ef5 100644 --- a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java +++ b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java @@ -14,22 +14,19 @@ public class VersionTest { @Test public void unknownVersionAsString() { - String versionText = BuildInfo.UNKNOWN_VERSION; - Version version = new Version(versionText); + Version version = new Version(BuildInfo.UNKNOWN_VERSION); assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); } @Test public void unknownVersionAsNull() { - String versionText = null; - Version version = new Version(versionText); + Version version = new Version(null); assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); } @Test public void unknownVersionAsEmptyString() { - String versionText = ""; - Version version = new Version(versionText); + Version version = new Version(""); assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); } @@ -113,6 +110,13 @@ public void validVersionIsNotNewerThanUnknownVersion() { assertFalse(validVersion.isNewerThan(unknownVersion)); } + @Test + public void unknownVersionIsNotNewerThanvalidVersion() { + Version unknownVersion = new Version(BuildInfo.UNKNOWN_VERSION); + Version validVersion = new Version("4.2"); + assertFalse(unknownVersion.isNewerThan(validVersion)); + } + @Test public void versionNewerThan() { Version olderVersion = new Version("2.4"); @@ -127,20 +131,6 @@ public void versionNotNewerThanSameVersion() { assertFalse(version1.isNewerThan(version2)); } - @Test - public void concreteVersionNewerThanUnknownVersion() { - Version concreteVersion = new Version("4.2"); - Version unknownVersion = new Version(BuildInfo.UNKNOWN_VERSION); - assertTrue(concreteVersion.isNewerThan(unknownVersion)); - } - - @Test - public void unknownVersionNotNewerThanConceteVersion() { - Version concreteVersion = new Version("4.2"); - Version unknownVersion = new Version(BuildInfo.UNKNOWN_VERSION); - assertTrue(unknownVersion.isNewerThan(concreteVersion)); - } - @Test public void versionNewerThanDevTwoDigits() { Version older = new Version("4.2"); @@ -173,7 +163,7 @@ public void versionNotNewerPatch() { public void equalVersionsNotNewer() { Version version1 = new Version("4.2.2"); Version version2 = new Version("4.2.2"); - assertTrue(version1.isNewerThan(version2)); + assertFalse(version1.isNewerThan(version2)); } @Test @@ -188,13 +178,6 @@ public void changelogWithThreeDigits(){ assertEquals("https://github.com/JabRef/jabref/blob/v3.4.1/CHANGELOG.md", version.getChangelogUrl()); } - @Test - public void versionNotReplaced() { - String versionText = "${version}"; - Version version = new Version(versionText); - assertEquals(BuildInfo.UNKNOWN_VERSION, version.getFullVersion()); - } - @Test public void versionNull() { String versionText = null; From 2febd794caf501c98f5e62a6cbd4038ca6cee7f3 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Thu, 30 Jun 2016 08:50:34 +0200 Subject: [PATCH 175/268] Fix Codacy issue --- src/main/java/net/sf/jabref/logic/util/Version.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java index 31fcafd6ef30..865d69b65c0e 100644 --- a/src/main/java/net/sf/jabref/logic/util/Version.java +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -90,10 +90,8 @@ public boolean isNewerThan(Version otherVersion) { } else if (this.getMajor() == otherVersion.getMajor()) { if (this.getMinor() > otherVersion.getMinor()) { return true; - } else if ((this.getMinor() == otherVersion.getMinor()) && (this.getPatch() > otherVersion.getPatch())) { - return true; } else { - return false; + return (this.getMinor() == otherVersion.getMinor()) && (this.getPatch() > otherVersion.getPatch()); } } else { return false; From 5be9546b1e9b3cb30ce0b842fbdd9c27abe9051b Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 30 Jun 2016 11:05:04 +0200 Subject: [PATCH 176/268] Updated German translation --- CHANGELOG.md | 1 + src/main/resources/l10n/JabRef_de.properties | 32 ++++++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b199b3e24b4f..f751d8718da2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Implemented [#661](https://github.com/JabRef/jabref/issues/661): Introducing a "check for updates" mechnism (manually/automatic at startup) - [#1485](https://github.com/JabRef/jabref/issues/1485): Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography - [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view +- Updated German translation ### Fixed - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index cbd7d36fe5a5..54e67e42cb1e 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2404,19 +2404,19 @@ Cleared_'%0'_for_%1_entries='%0'_für_%1_Einträge_entfernt Set_'%0'_to_'%1'_for_%2_entries='%0'_für_%2_Einträge_auf_'%1'_gesetzt Toggled_'%0'_for_%1_entries='%0'_für_%1_Einträge_geändert -Check_for_updates= -Download_update= -New_version_available= -Installed_version= -Remind_me_later= -Ignore_this_update= -Couldn't_connect_to_the_update_server.= -Please_try_again_later_and/or_check_your_network_connection.= -To_see_what's_new_view_the_changelog.= -A_new_version_of_JabRef_has_been_released.= -JabRef_is_up-to-date.= -Latest_version= - -Please_open_%0_manually.= - -The_link_has_been_copied_to_the_clipboard.= +Check_for_updates=Prüfe_auf_Aktualisierungen +Download_update=Aktualisierung_herunterladen +New_version_available=Neue_Version_vefügbar +Installed_version=Installierte_Version +Remind_me_later=Später_erinnern +Ignore_this_update=Diese_Aktualisierung_ignorieren +Couldn't_connect_to_the_update_server.=Konnte_nicht_zum_Aktualisierungsserver_verbinden. +Please_try_again_later_and/or_check_your_network_connection.=Bitte_versuchen_Sie_es_später_erneut_und/oder_prüfen_Sie_ihre_Netzwerkverbindung. +To_see_what's_new_view_the_changelog.=Für_Neuerungen/Änderungen_Changelog_ansehen. +A_new_version_of_JabRef_has_been_released.=Eine_neue_JabRef_Version_wurde_veröffentlicht. +JabRef_is_up-to-date.=JabRef_ist_auf_dem_aktuellsten_Stand. +Latest_version=Neueste_Version + +Please_open_%0_manually.=Bitte_öffnen_Sie_%0_manuell. + +The_link_has_been_copied_to_the_clipboard.=Der_Link_wurde_in_die_Zwischenablage_kopiert. From 1fedf6b950aeaddf50e77bd315f66ae3bd601615 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 1 Jul 2016 11:08:06 +0200 Subject: [PATCH 177/268] Fix codacy issue: "Avoid using redundant field initializer" --- src/main/java/net/sf/jabref/logic/util/Version.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java index 865d69b65c0e..2be5b057d599 100644 --- a/src/main/java/net/sf/jabref/logic/util/Version.java +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -37,10 +37,10 @@ public class Version { private final static String JABREF_GITHUB_URL = "https://api.github.com/repos/JabRef/jabref/releases/latest"; private String fullVersion = BuildInfo.UNKNOWN_VERSION; - private int major = 0; - private int minor = 0; - private int patch = 0; - private boolean isDevelopmentVersion = false; + private int major; + private int minor; + private int patch; + private boolean isDevelopmentVersion; /** * @param version must be in form of X.X (e.g., 3.3; 3.4dev) From 8b14b0bb0c4b9c2069e4c81611ef9c33fccc8904 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 1 Jul 2016 11:13:36 +0200 Subject: [PATCH 178/268] increase test coverage --- .../java/net/sf/jabref/logic/util/version/VersionTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java index a7b4811b6ef5..0509eabdc868 100644 --- a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java +++ b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java @@ -124,6 +124,13 @@ public void versionNewerThan() { assertTrue(newerVersion.isNewerThan(olderVersion)); } + @Test + public void versionNotNewerThan() { + Version olderVersion = new Version("2.4"); + Version newerVersion = new Version("4.2"); + assertFalse(olderVersion.isNewerThan(newerVersion)); + } + @Test public void versionNotNewerThanSameVersion() { Version version1 = new Version("4.2"); From cfac37604ea05db7c9fec5194036f40001f18f57 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 1 Jul 2016 17:07:20 +0200 Subject: [PATCH 179/268] Add tests for checking minor version --- .../sf/jabref/logic/util/version/VersionTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java index 0509eabdc868..be384f8b956b 100644 --- a/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java +++ b/src/test/java/net/sf/jabref/logic/util/version/VersionTest.java @@ -152,6 +152,20 @@ public void versionNewerThanDevThreeDigits() { assertTrue(newer.isNewerThan(older)); } + @Test + public void versionNewerMinor() { + Version older = new Version("4.1"); + Version newer = new Version("4.2.1"); + assertTrue(newer.isNewerThan(older)); + } + + @Test + public void versionNotNewerMinor() { + Version older = new Version("4.1"); + Version newer = new Version("4.2.1"); + assertFalse(older.isNewerThan(newer)); + } + @Test public void versionNewerPatch() { Version older = new Version("4.2.1"); From b376621246652241217db82f7ddff100f3b110fe Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 2 Jul 2016 14:23:00 +0200 Subject: [PATCH 180/268] Some Swedish translations (#1537) --- src/main/resources/l10n/JabRef_sv.properties | 148 +++++++++---------- src/main/resources/l10n/Menu_sv.properties | 2 +- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 687ffd85d7da..7f3f60ac4105 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -409,8 +409,8 @@ Entry_types=Posttyper Error=Fel Error_creating_email=Fel_vid_skapande_av_epost Error_downloading_file_'%0'=Fel_när_filen_'%0'_skulle laddas_ned -Error_exporting_to_clipboard= -Error_importing_from_database= +Error_exporting_to_clipboard=Fel_vid_export_till_urklipp +Error_importing_from_database=Fel_vid_import_från_databas Error_message\:=Felmeddelande\: Error_occurred_when_parsing_entry= Error_opening_autosave_of_'%0'._Trying_to_load_'%0'_instead.= @@ -421,7 +421,7 @@ Error_while_downloading_file\:=Fel_vid_nedladdning_av_fil\: Error_while_fetching_from_%0= Error_while_writing= Error_writing_to_%0_file(s).= -Establishing_SQL_connection...= +Establishing_SQL_connection...=Kopplar_upp_mot_SQL-databas... Exceptions= Existing_file=Existerande_fil Expand_all=Expandera_alla @@ -487,7 +487,7 @@ Filter=Filtrera Find_and_remove_duplicate_BibTeX_keys=Hitta_och_ta_bort_duplicerade_BibTeX-nycklar Find_unlinked_files=Hitta_olänkade_filer Finished_automatically_setting_external_links.= -Finished_downloading_full_text_document= +Finished_downloading_full_text_document=Nedladdning_av_dokument_avslutad Finished_resolving_duplicate_BibTeX_keys._%0_entries_modified.= Finished_synchronizing_file_links._Entries_changed\:_%0.= Finished_writing_XMP-metadata._Wrote_to_%0_file(s).= @@ -520,7 +520,7 @@ Full_name= General=Generellt General_fields=Generella_fält General_file_directory=Generell_filmapp -Full_text_document_download_failed= +Full_text_document_download_failed=Gick_inte_att_ladda_ned_dokument. Generate=Generera Generate_BibTeX_key=Generera_BibTeX-nyckel Generate_groups_for_author_last_names=Generera_grupper_baserat_på_författarefternamn @@ -545,8 +545,8 @@ HTML_table=HTML-tabell HTML_table_(with_Abstract_&_BibTeX)= Have_you_chosen_the_correct_package_path?=Har_du_valt_rätt_sökväg_till_paketet? Help=Hjälp -Help_on_Name_Formatting= -Help_on_Regular_Expression_Search= +Help_on_Name_Formatting=Hjälp_för_namnformattering +Help_on_Regular_Expression_Search=Hjälp_för_sökning_med_reguljära_uttryck Help_on_groups=Hjälp_för_grupper Help_on_key_patterns=Hjälp_för_nyckelmönster Help_on_special_fields=Hjälp_för_specialfält @@ -584,7 +584,7 @@ Import_group_definitions= Import_into_current_database=Importera_till_nuvarande_databas Import_into_new_database=Importera_till_ny_databas Import_marking_color=Färg_för_importerade_poster -Import_metadata_from\:= +Import_metadata_from\:=Importera_metadata_från\: Import_name= Import_preferences=Importera_inställningar Import_preferences_from_file=Importera_inställningar_från_fil @@ -595,7 +595,7 @@ Imported_%0_databases_successfully=Importerade_%0_databaser_framgångsrikt Imported_entries=Importerade_poster Imported_from_database=Importerade_från_databas Importing=Importerar -Importing_canceled= +Importing_canceled=Importen_avbruten Importing_in_unknown_format=Importerar_i_okänt_format Importing_into_Database...=Importerar_till_databas... Include_abstracts=Inkludera_sammanfattning @@ -610,7 +610,7 @@ Insert_URL=Infoga_URL Insert_a_citation_without_text_(the_entry_will_appear_in_the_reference_list)= Insert_empty_citation=Infoga_tom_citering Insert_rows=Infoga_rader -Intersection= +Intersection=Snitt Invalid_BibTeX_key=Ogiltig_BibTeX-nyckel Invalid_DOI\:_'%0'.=Ogiltig_DOI\:_'%0'. Invalid_URL=Ogiltig_URL @@ -643,7 +643,7 @@ Last_modified=Senast_ändrad Leave_file_in_its_current_directory=Lämna_filen_i_nuvarande_mapp Leave_this_dialog.=Lämna_denna_dialog. Left=Vänster -Level= +Level=Nivå Left_entry=Vänster_post Limit_to_fields=Begränsa_till_fält Limit_to_selected_entries=Begränsa_till_valda_poster @@ -819,12 +819,12 @@ Other_fields=Andra_fält Output= Output_file_missing= Output_or_export_file= -Override= -Override_default_file_directories= -Override_default_font_settings= +Override=Ignorera +Override_default_file_directories=Ignorerar_normala_filmappar +Override_default_font_settings=Ignorera_normala_typsnittsinställningar Override_the_BibTeX_field_by_the_selected_text= Overwrite=Skriv_över -Overwrite_existing_field_values= +Overwrite_existing_field_values=Skriv_över_befintligt_fältinnehåll Overwrite_file?=Skriva_över_fil? Overwrite_key=Skriv_över_nyckel Overwrite_keys=Skriv_över_nycklar @@ -854,7 +854,7 @@ Please_enter_the_desired_name\:=Ange_det_önskade_namnet\: Please_enter_the_field_to_search_(e.g._keywords)_and_the_keyword_to_search_it_for_(e.g._electrical).= Please_enter_the_string's_label=Ange_namnet_på_strängen Please_move_the_file_manually_and_link_in_place.= -Please_open_or_start_a_new_database_before_searching= +Please_open_or_start_a_new_database_before_searching=Öppna_eller_skapa_en_ny_databas_innan_sökning. Please_select_an_importer.= Please_select_exactly_one_group_to_move.=Välj_exakt_en_grupp_att_flytta. Please_select_which_JabRef_databases_do_you_want_to_import\:= @@ -866,14 +866,14 @@ Port=Port Possible_duplicate_entries=Möjliga_dubbletter Possible_duplicate_of_existing_entry._Click_to_resolve.=Möjlig_dubblett_av_befintlig_post._Klicka_för_att_reda_ut. Preamble=Preamble -Preamble_editor,_store_changes= +Preamble_editor,_store_changes=Preamble-editorn,_spara_ändringar Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Preferences=Inställningar -Preferences_recorded.= +Preferences_recorded.=Inställningar_sparade. Preview=Postvisning Previous_entry=Föregående_post Previous_tab=Föregående_flik -Primary_sort_criterion= +Primary_sort_criterion=Första_sorteringskriteriet Print_entry_preview=Skriv_ut_postvisning Printed=Utskriven Priority=Prioritet @@ -884,7 +884,7 @@ Problem_modifying_citation=Problem_att_modifiera_citering Problem_with_parsing_entry=Problem_att_tolka_post Processing_%0=Behandlar_%0 Program_output= -Progress\:_%0_of_%1= +Progress\:_%0_of_%1=Händelseförlopp\:_%0_av_%1 Prompt_before_recovering_a_database_from_an_autosave_file= Protected_database=Skyddad_databas Proxy_requires_authentication=Proxyn_kräver_autentisering @@ -901,25 +901,25 @@ Raw_source=Rå_källkod Read_status=Lässtatus Read_status_read=Läst Read_status_skimmed=Skummat -Really_delete_the_selected_%0_entries?= -Really_delete_the_selected_entry?= +Really_delete_the_selected_%0_entries?=Verkligen_ta_bort_de_%0_valda_posterna? +Really_delete_the_selected_entry?=Verkligen_ta_bort_den_valda_posten? Rearrange_tabs_alphabetically_by_title= Rebind_C-a,_too= Rebind_C-f,_too= -Recover_from_autosave= -Redo= +Recover_from_autosave=Återställ_från_automatiskt_sparad_fil +Redo=Gör_igen Reference_database=Referensdatabas References=Referenser -References_found= +References_found=Referenser_hittade Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup= Refresh_OpenOffice/LibreOffice=Uppdatera_OpenOffice/LibreOffice Refuse_to_save_the_database_before_external_changes_have_been_reviewed.= -Regenerate_all_keys_for_the_entries_in_a_BibTeX_file= -Regenerating_BibTeX_keys_according_to_metadata= +Regenerate_all_keys_for_the_entries_in_a_BibTeX_file=Generera_BibTeX-nycklar_för_alla_poster_i_en_BibTeX-fil +Regenerating_BibTeX_keys_according_to_metadata=Generera_BibTeX-nycklar_enligt_metadata Relevance=Relevans -Remember_these_entry_types?= +Remember_these_entry_types?=Kom_ihåg_dessa_posttyper? Remote_operation=Fjärrstyrning -Remote_server_port= +Remote_server_port=Port_på_fjärrserver Remove=Ta_bort Remove_selected=Ta_bort_valda Remove_all_broken_links=Ta_bort_alla_trasiga_länkar @@ -950,7 +950,7 @@ Rename_file_to=Byt_namn_på_fil_till Rename_only_PDFs_having_a_relative_path= Rename_to_'%0'=Byt_namn_till_'%0' Renamed_string=Bytte_namn_på_sträng -Replace_(regular_expression)= +Replace_(regular_expression)=Ersätt_(reguljärt_uttryck) Replace_original_entry=Ersätt_ursprunglig_post Replace_string=Ersätt_sträng Replace_with=Ersätt_med @@ -979,7 +979,7 @@ Running_Query_'%0'_with_fetcher_'%1'.= SQL_Database_Exporter= SQL_Database_Importer= SQL_Export= -SQL_connection_established.= +SQL_connection_established.=Ansluten_till_SQL-databas. Save=Spara Save_actions= Save_all=Spara_alla @@ -1020,7 +1020,7 @@ Searching...=Söker... Searching_file_system...=Söker_på_filsystemet... Searching_for_duplicates...=Söker_efter_dubbletter... Searching_for_files=Söker_efter_filer -Secondary_sort_criterion= +Secondary_sort_criterion=Andra_sorteringskriteriet Select=Välj Select_Classpath_of_New_Importer= Select_Writer_document=Välj_Writer-dokument @@ -1144,11 +1144,11 @@ Table_row_height_padding= Table_text_color=Textfärg_för_tabellen Tabname=Fliknamn Target_file_cannot_be_a_directory.=Målfilen_kan_inte_vara_en_mapp. -Tertiary_sort_criterion= +Tertiary_sort_criterion=Tredje_sorteringskriteriet Test= -The_ACM_Digital_Library= +The_ACM_Digital_Library=ACMs_digitala_bibliotek The_Guide_to_Computing_Literature= -The_PDF_contains_one_or_several_BibTeX-records.= +The_PDF_contains_one_or_several_BibTeX-records.=PDFen_innehåller_en_eller_flera_BibTeX-poster. The_Zip-archive_need_not_be_on_the_classpath_of_JabRef.= The_character_format_is_controlled_by_the_citation_property_'CitationCharacterFormat'_in_the_style_file.= The_chosen_date_format_for_new_entries_is_not_valid=Det_valda_datumformatet_för_nya_poster_är_inte_giltigt @@ -1160,12 +1160,12 @@ The_group_"%0"_already_contains_the_selection.= The_label_of_the_string_cannot_be_a_number.=Strängnamnet_kan_inte_vara_ett_tal. The_label_of_the_string_cannot_contain_spaces.=Strängnamnet_kan_inte_innehålla_mellanslag. The_label_of_the_string_cannot_contain_the_'\#'_character.=Strängnamnet_kan_inte_innehålla_tecknet_'\#'. -The_name_'comment'_cannot_be_used_as_an_entry_type_name.= +The_name_'comment'_cannot_be_used_as_an_entry_type_name.=En_posttyp_kan_inte_döpas_till_'comment'. The_output_option_depends_on_a_valid_import_option.= The_output_option_depends_on_a_valid_input_option.= The_paragraph_format_is_controlled_by_the_property_'ReferenceParagraphFormat'_or_'ReferenceHeaderParagraphFormat'_in_the_style_file.= The_path_need_not_be_on_the_classpath_of_JabRef.= -The_regular_expression_%0_is_invalid\:= +The_regular_expression_%0_is_invalid\:=Det_reguljära_uttycket_%0_är_ogiltigt\: The_search_is_case_insensitive.=Sökningen_är_inte_skiftlägeskänslig. The_search_is_case_sensitive.=Sökningen_är_skiftlägeskänslig. The_string_has_been_removed_locally=Strängen_har_tagit_bort_lokalt @@ -1185,14 +1185,14 @@ This_feature_lets_new_files_be_opened_or_imported_into_an_already_running_instan This_group_contains_all_entries._It_cannot_be_edited_or_removed.=Denna_grupp_innehåller_alla_poster._Den_kan_inte_ändras_eller_tas_bort. This_group_contains_entries_based_on_manual_assignment._Entries_can_be_assigned_to_this_group_by_selecting_them_then_using_either_drag_and_drop_or_the_context_menu._Entries_can_be_removed_from_this_group_by_selecting_them_then_using_the_context_menu.= This_group_contains_entries_whose_%0_field_contains_the_keyword_%1=Denna_grupp_innehåller_poster_där_fältet_%0_innehåller_nyckelordet_%1 -This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1= +This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Denna_grupp_innehåller_poster_där_fältet_%0_innehåller_det_reguljära_uttrycket_%1 This_is_a_simple_copy_and_paste_dialog._First_load_or_paste_some_text_into_the_text_input_area.
    After_that,_you_can_mark_text_and_assign_it_to_a_BibTeX_field.= This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.= This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Denna_operationen_kräver_att_alla_valda_poster_har_en_BibTeX-nyckel. This_operation_requires_at_least_one_entry.=Denna_operationen_kräver_minst_en_post. This_operation_requires_one_or_more_entries_to_be_selected.=Den_här_operationen_kräver_att_en_eller_flera_poster_är_valda. This_search_contains_entries_in_which=Denna_sökning_innehåller_poster_där -This_search_contains_entries_in_which_any_field_contains_the_regular_expression_%0= +This_search_contains_entries_in_which_any_field_contains_the_regular_expression_%0=Denna_sökning_innehåller_poster_där_något_fält_innehåller_det_reguljära_uttrycket_%0 This_search_contains_entries_in_which_any_field_contains_the_term_%0=Denna_sökning_innehåller_poster_där_något_fält_innehåller_termen_%0 Three_stars=Tre_stjärnor Title=Titel @@ -1225,7 +1225,7 @@ Unable_to_save_database=Kan_inte_spara_databas Unable_to_synchronize_bibliography=Kan_inte_synkronisera_bibliografi Undefined_file_type=Odefinierad_filtyp Undo=Ångra -Union= +Union=Union Unknown_DOI\:_'%0'.=Okänt_DOI\:_'%0' Unknown_DiVA_entry\:_'%0'.=Okänd_DiVA-post\:_'%0' Unknown_BibTeX_entries=Okända_BibTeX-poster @@ -1257,7 +1257,7 @@ Use=Använd Use_EMACS_23_insertion_string= Use_Emacs_key_bindings=Använd_tangentbordsbindningar_som_i_Emacs Use_IEEE_LaTeX_abbreviations=Använd_IEEE_LaTeX-förkortningar -Use_regular_expression_search= +Use_regular_expression_search=Använd_sökning_med_reguljära_uttryck Use_abbreviated_and_full_firstname=Använd_förkortade_och_hela_förnamn Use_abbreviated_firstname_whenever_possible=Använd_om_möjligt_förkortade_förnamn Use_autocompletion_for_the_following_fields= @@ -1309,10 +1309,10 @@ You_have_changed_the_menu_and_label_font_size.= You_have_entered_an_invalid_or_already_existent_DB_name.= You_have_entered_an_invalid_search_'%0'.=Du_har_angett_en_ogiltig_sökning_'%0'. You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= -You_have_to_choose_exactly_two_entries_to_merge.= +You_have_to_choose_exactly_two_entries_to_merge.=Du_måste_välja_exakt_två_poster_att_slå_samman. You_must_choose_a_filename_to_store_journal_abbreviations=Du_måste_välja_ett_filnamn_för_att_spara_tidskriftsförkortningar -You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for= -You_must_enter_an_integer_value_in_the_text_field_for= +You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Du_måste_ange_ett_heltal_i_området_1025-65536_i_fältet_för +You_must_enter_an_integer_value_in_the_text_field_for=Du_måste_ange_ett_heltal_i_fältet_för You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=Du_måste_starta_om_JabRef_för_att_tangentbordsbindningarna_ska_fungera_ordentligt. You_must_restart_JabRef_for_this_to_come_into_effect.=Du_måste_starta_om_JabRef_för_att_ändringen_ska_slå_igenom. You_must_select_either_a_valid_style_file,_or_use_one_of_the_default_styles.= @@ -1325,7 +1325,7 @@ abbreviation_detected=förkortning_upptäcktes add_group=lägg_till_grupp and=och and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.= -any_field_that_matches_the_regular_expression_%0= +any_field_that_matches_the_regular_expression_%0=något_fält_som_matchar_det_reguljära_uttrycket_%0 by=med case_insensitive=ej_skiftlägeskänsligt case_sensitive=skiftlägeskänsligt @@ -1358,8 +1358,8 @@ includes_subgroups=inkluderar_undergrupper insert_string=infoga_sträng key=nyckel keys_in_database=nycklar_i_databas -large_capitals_are_not_masked_using_curly_brackets_{}= -link_should_refer_to_a_correct_file_path= +large_capitals_are_not_masked_using_curly_brackets_{}=stora_bokstäver_är_inte_skyddade_med_måsvingar_{} +link_should_refer_to_a_correct_file_path=länken_ska_ange_en_korrekt_sökväg modify_group=ändra_grupp move_group=flytta_grupp nested_aux_files=nästlade_aux-filer @@ -1385,7 +1385,7 @@ resolved= search_expression=sökuttryck should_contain_a_four_digit_number=ska_innehålla_ett_fyrsiffrigt_tal should_contain_a_protocol=ska_innehålla_ett_protokoll -should_contain_a_valid_page_number_range= +should_contain_a_valid_page_number_range=ska_innehålla_ett_giltligt_sidintervall should_end_with_a_name=ska_avslutas_med_ett_namn should_start_with_a_name=ska_börja_med_ett_namn sort_subgroups=sortera_undergrupper @@ -1400,10 +1400,10 @@ unknown_edit=okänd_ändring untitled=namnlös usage=användning value=värde -verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid= +verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=kontrollera_att_LyX_körs_och_att_lyxpipe_är_korrekt web_link=weblänk with=med -wrong_entry_type_as_proceedings_has_page_numbers= +wrong_entry_type_as_proceedings_has_page_numbers=fel_posttyp_eftersom_proceeding_har_sidnummer %0_import_canceled=Import_från_%0_avbruten Internal_style=Intern_stil @@ -1425,7 +1425,7 @@ Cleans_up_LaTeX_code.=Städar_upp_i_LaTeX-koden. Converts_HTML_code_to_LaTeX_code.=Konverterar_HTML-koder_till_LaTeX-kod. Converts_LaTeX_encoding_to_Unicode_characters.=Konverterar_Latex-koder_till_Unicode-tecken. Converts_Unicode_characters_to_LaTeX_encoding.=Konverterar_Unicode-tecken_till_LaTeX-kod. -Converts_ordinals_to_LaTeX_superscripts.= +Converts_ordinals_to_LaTeX_superscripts.=Konverterar_ordningsnummer_till_LaTeX_\\superscript{}. HTML_to_LaTeX=HTML_till_LaTeX LaTeX_cleanup=LaTeX-städning LaTeX_to_Unicode=LaTeX_till_Unicode @@ -1438,7 +1438,7 @@ Normalize_page_numbers=Normalisera_sidnummer Normalize_pages_to_BibTeX_standard.=Normaliserar_sidnummer_till_BibTeX-standard. Normalizes_lists_of_persons_to_the_BibTeX_standard.=Normaliserar_personnamn_till_BibTeX-standard. Normalizes_the_date_to_ISO_date_format.=Normaliserar_datum_till_ISO-standardformat. -Ordinals_to_LaTeX_superscript= +Ordinals_to_LaTeX_superscript=Ordningsnummer_till_LaTeX_\\superscript{} Protect_terms=Skydda_termer Remove_enclosing_braces=Ta_bort_inneslutande_måsvingar Removes_braces_encapsulating_the_complete_field_content.=Ta_bort_måsvingar_som_innesluter_hela_fältet. @@ -1452,7 +1452,7 @@ Identity=Identitet Clears_the_field_completely.=Tömmer_fältet_helt. Directory_not_found=Kan_ej_hitta_mapp -Main_file_directory_not_set\!= +Main_file_directory_not_set\!=Huvudfilmapp_ej_satt\! This_operation_requires_exactly_one_item_to_be_selected.=Denna_operationen_kräver_att_exakt_en_post_är_vald. @@ -1475,8 +1475,8 @@ Lookup_DOI=Leta_efter_DOI No_DOI_found=Inget_DOI_hittades Audio_CD=Ljud-CD -British_patent= -British_patent_request= +British_patent=Brittiskt_patent +British_patent_request=Brittisk_patentansökan Candidate_thesis=Kandidatarbete Collaborator=Medarbetare Column=Kolumn @@ -1492,7 +1492,7 @@ French_patent_request=Fransk_patentansökan German_patent=Tyskt_patent German_patent_request=Tysk_patentansökan Line=Rad -Master's_thesis= +Master's_thesis=Magisteruppsats Page=Sida Paragraph=Stycke Patent=Patent @@ -1518,7 +1518,7 @@ word=ord Show_symmetric_diff=Visa_skillnad_symmetriskt -booktitle_ends_with_'conference_on'= +booktitle_ends_with_'conference_on'=boktiteln_slutar_med_'conference_on' HTML_encoded_character_found=HTML-kodade_tecken_hittades All_external_files=Alla_externa_filer @@ -1529,7 +1529,7 @@ incorrect_control_digit=felaktig_kontrollsiffra incorrect_format=felaktigit_format Expected_"%0"_to_contain_whitespace=Förväntade_"%0"_att_innehålla_mellanslag -Syntax_error_in_regular-expression_pattern= +Syntax_error_in_regular-expression_pattern=Syntaxfel_i_det_reguljära_uttrycket Copy_version_to_clipboard=Kopiera_version_till_urklipp Copied_version_to_clipboard=Kopierade_version_till_urklipp @@ -1537,27 +1537,27 @@ Copied_version_to_clipboard=Kopierade_version_till_urklipp BibTeX_key=BibTeX-nyckel Message=Meddelande -Get_fulltext= +Get_fulltext=Hämta_dokument Download_from_URL=Ladda_ned_från_URL Decryption_not_supported.=Avkryptering_stöds_ej. Cleared_'%0'_for_%1_entries=Rensade_'%0'_för_%1_poster -Set_'%0'_to_'%1'_for_%2_entries= +Set_'%0'_to_'%1'_for_%2_entries=Satta_'%0'_till_'%1'_för_%2_poster Toggled_'%0'_for_%1_entries=Växlade_'%0'_för_%1_poster -Check_for_updates= -Download_update= -New_version_available= -Installed_version= -Remind_me_later= -Ignore_this_update= -Couldn't_connect_to_the_update_server.= -Please_try_again_later_and/or_check_your_network_connection.= -To_see_what's_new_view_the_changelog.= -A_new_version_of_JabRef_has_been_released.= -JabRef_is_up-to-date.= -Latest_version= +Check_for_updates=Sök_efter_uppdateringar +Download_update=Ladda_ned_uppdatering +New_version_available=Ny_version_tillgänglig +Installed_version=Installerad_version +Remind_me_later=Påminn_mig_senare +Ignore_this_update=Ignorerar_den_här_uppdateringen. +Couldn't_connect_to_the_update_server.=Kunde_inte_ansluta_till_uppdateringsservern. +Please_try_again_later_and/or_check_your_network_connection.=Försök_igen_senare_och/eller_kontrollera_din_internetuppkoppling. +To_see_what's_new_view_the_changelog.=För_att_få_reda_på_vad_som_är_nytt_se_ändringsloggen. +A_new_version_of_JabRef_has_been_released.=En_ny_version_av_JabRef_har_släppts- +JabRef_is_up-to-date.=JabRef_är_uppdaterad. +Latest_version=Senaste_version -Please_open_%0_manually.= +Please_open_%0_manually.=Öppna_%0_för_hand. -The_link_has_been_copied_to_the_clipboard.= +The_link_has_been_copied_to_the_clipboard.=Länken_har_kopierats_till_urklipp. diff --git a/src/main/resources/l10n/Menu_sv.properties b/src/main/resources/l10n/Menu_sv.properties index 55e78b9a79ea..59f7c2cff29b 100644 --- a/src/main/resources/l10n/Menu_sv.properties +++ b/src/main/resources/l10n/Menu_sv.properties @@ -23,7 +23,7 @@ Help=&Hjälp Highlight_groups_matching_all_selected_entries=Framhäv_grupper_som_matchar_alla_valda_poster Highlight_groups_matching_any_selected_entry=Framhäv_grupper_som_matchar_någon_vald_poster Disable_highlight_groups_matching_entries=Framhäv_inte_grupper_som_matcher_poster -Online_help= +Online_help=Online&hjälp Donate_to_JabRef=Donera_till_JabRef Manage_content_selectors=Hantera_innehållsväljare Manage_custom_exports=Hantera_egna_exporterare From 632fbf6243c602761e246315505f894b644c7d6e Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 6 Jul 2016 14:43:07 +0200 Subject: [PATCH 181/268] Some code cleanups (#1546) --- .../java/net/sf/jabref/gui/ContentSelectorDialog2.java | 10 +++++----- .../net/sf/jabref/gui/entryeditor/EntryEditor.java | 4 +--- .../java/net/sf/jabref/gui/groups/GroupSelector.java | 4 ++-- .../importer/fileformat/MedlinePlainImporter.java | 2 ++ .../jabref/importer/fileformat/PdfContentImporter.java | 2 +- .../sf/jabref/logic/cleanup/FieldFormatterCleanup.java | 3 +-- .../java/net/sf/jabref/logic/groups/KeywordGroup.java | 2 +- src/main/java/net/sf/jabref/logic/util/BuildInfo.java | 8 ++++---- src/main/java/net/sf/jabref/logic/util/Version.java | 4 ++-- .../java/net/sf/jabref/model/database/EntrySorter.java | 2 -- 10 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java index aa22ed1ac1ff..d2a7b81ee115 100644 --- a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java +++ b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java @@ -268,12 +268,12 @@ private void applyChanges() { } // Cycle through all fields that we have created listmodels for: - for (String fieldName : wordListModels.keySet()) { + for (Map.Entry> entry : wordListModels.entrySet()) { // For each field name, store the values: - if ((fieldName == null) || FIELD_FIRST_LINE.equals(fieldName)) { + if ((entry.getKey() == null) || FIELD_FIRST_LINE.equals(entry.getKey())) { continue; } - DefaultListModel lm = wordListModels.get(fieldName); + DefaultListModel lm = entry.getValue(); int start = 0; // Avoid storing the marker if it is there: if (!lm.isEmpty()) { @@ -282,14 +282,14 @@ private void applyChanges() { } } - if (metaData.getContentSelectors(fieldName).isEmpty()) { + if (metaData.getContentSelectors(entry.getKey()).isEmpty()) { changedFieldSet = true; List data = new ArrayList<>(); for (int wrd = start; wrd < lm.size(); wrd++) { String word = lm.get(wrd); data.add(word); } - metaData.setContentSelectors(fieldName, data); + metaData.setContentSelectors(entry.getKey(), data); } } diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 93d8a0f7cc0c..9b528f1f90ff 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -35,7 +35,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -529,8 +528,7 @@ public Optional getExtra(final FieldEditor editor) { } else if (fieldExtras.contains(FieldProperties.PAGINATION)) { return FieldExtraComponents.getPaginationExtraComponent(editor, this); } else if (fieldExtras.contains(FieldProperties.TYPE)) { - return FieldExtraComponents.getTypeExtraComponent(editor, this, - "patent".equals(entry.getType().toLowerCase(Locale.ENGLISH))); + return FieldExtraComponents.getTypeExtraComponent(editor, this, "patent".equalsIgnoreCase(entry.getType())); } return Optional.empty(); } diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index a0b3471a60a4..38af9d100b23 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -495,7 +495,7 @@ private void showPopup(MouseEvent e) { moveNodeRightPopupAction.setNode(node); // add/remove entries to/from group List selection = frame.getCurrentBasePanel().getSelectedEntries(); - if (selection.size() > 0) { + if (!selection.isEmpty()) { if (node.canAddEntries(selection)) { addToGroup.setNode(node); addToGroup.setBasePanel(panel); @@ -722,7 +722,7 @@ public void componentClosing() { private void setGroups(GroupTreeNode groupsRoot) { this.groupsRoot = new GroupTreeNodeViewModel(groupsRoot); - this.groupsRoot.subscribeToDescendantChanged(source -> groupsTreeModel.nodeStructureChanged(source)); + this.groupsRoot.subscribeToDescendantChanged(groupsTreeModel::nodeStructureChanged); groupsTreeModel = new DefaultTreeModel(this.groupsRoot); groupsTree.setModel(groupsTreeModel); if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_EXPAND_TREE)) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index e416191ef3e2..f6da32045770 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -263,6 +263,8 @@ private String addSourceType(String value, String type) { case "overall": theType = "proceedings"; break; + default: + break; } if ("".equals(theType)) { theType = "other"; diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index 3e6c49a78229..069899118347 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -216,7 +216,7 @@ public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { if (doi.isPresent()) { ParserResult parserResult = new ParserResult(result); Optional entry = DOI_TO_BIBTEX_FETCHER.getEntryFromDOI(doi.get().getDOI(), parserResult); - entry.ifPresent(e -> parserResult.getDatabase().insertEntry(e)); + entry.ifPresent(parserResult.getDatabase()::insertEntry); return parserResult; } 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 a4c54ec32933..07ecaff8f78f 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java @@ -17,7 +17,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.Objects; import net.sf.jabref.logic.formatter.Formatter; @@ -39,7 +38,7 @@ public FieldFormatterCleanup(String field, Formatter formatter) { @Override public List cleanup(BibEntry entry) { - if ("all".equals(field.toLowerCase(Locale.ENGLISH))) { + if ("all".equalsIgnoreCase(field)) { return cleanupAllFields(entry); } else { return cleanupSingleField(field, entry); diff --git a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java index 6b8beb616dbe..051c726141f1 100644 --- a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java @@ -160,7 +160,7 @@ public Optional remove(List entriesToRemove) { return Optional.empty(); } - if ((entriesToRemove != null) && (entriesToRemove.size() > 0)) { + if ((entriesToRemove != null) && (!entriesToRemove.isEmpty())) { List changes = new ArrayList<>(); boolean modified = false; for (BibEntry entry : entriesToRemove) { diff --git a/src/main/java/net/sf/jabref/logic/util/BuildInfo.java b/src/main/java/net/sf/jabref/logic/util/BuildInfo.java index 05fd18f21fde..27a90912199c 100644 --- a/src/main/java/net/sf/jabref/logic/util/BuildInfo.java +++ b/src/main/java/net/sf/jabref/logic/util/BuildInfo.java @@ -23,10 +23,10 @@ public class BuildInfo { public static final String UNKNOWN_VERSION = "*unknown*"; - public final static String OS = System.getProperty("os.name", UNKNOWN_VERSION).toLowerCase(); - public final static String OS_VERSION = System.getProperty("os.version", UNKNOWN_VERSION).toLowerCase(); - public final static String OS_ARCH = System.getProperty("os.arch", UNKNOWN_VERSION).toLowerCase(); - public final static String JAVA_VERSION = System.getProperty("java.version", UNKNOWN_VERSION).toLowerCase(); + public static final String OS = System.getProperty("os.name", UNKNOWN_VERSION).toLowerCase(); + public static final String OS_VERSION = System.getProperty("os.version", UNKNOWN_VERSION).toLowerCase(); + public static final String OS_ARCH = System.getProperty("os.arch", UNKNOWN_VERSION).toLowerCase(); + public static final String JAVA_VERSION = System.getProperty("java.version", UNKNOWN_VERSION).toLowerCase(); private final Version version; private final String authors; diff --git a/src/main/java/net/sf/jabref/logic/util/Version.java b/src/main/java/net/sf/jabref/logic/util/Version.java index 2be5b057d599..87f7c7b46664 100644 --- a/src/main/java/net/sf/jabref/logic/util/Version.java +++ b/src/main/java/net/sf/jabref/logic/util/Version.java @@ -32,9 +32,9 @@ */ public class Version { - public final static String JABREF_DOWNLOAD_URL = "http://www.fosshub.com/JabRef.html"; + public static final String JABREF_DOWNLOAD_URL = "http://www.fosshub.com/JabRef.html"; private static final Log LOGGER = LogFactory.getLog(Version.class); - private final static String JABREF_GITHUB_URL = "https://api.github.com/repos/JabRef/jabref/releases/latest"; + private static final String JABREF_GITHUB_URL = "https://api.github.com/repos/JabRef/jabref/releases/latest"; private String fullVersion = BuildInfo.UNKNOWN_VERSION; private int major; diff --git a/src/main/java/net/sf/jabref/model/database/EntrySorter.java b/src/main/java/net/sf/jabref/model/database/EntrySorter.java index e7cd9fb96321..1d078cd79f82 100644 --- a/src/main/java/net/sf/jabref/model/database/EntrySorter.java +++ b/src/main/java/net/sf/jabref/model/database/EntrySorter.java @@ -31,11 +31,9 @@ public class EntrySorter { // guarded by itself private final List entries; - private final Comparator comp; public EntrySorter(List entries, Comparator comparator) { this.entries = new ArrayList<>(entries); - this.comp = comparator; Collections.sort(this.entries, comparator); } From d5b42a0787c216330f0f7a49cd9d521e7d66a2f8 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 6 Jul 2016 18:18:34 +0200 Subject: [PATCH 182/268] Minor improvement for duplicate key resolving dialog (#1544) --- CHANGELOG.md | 1 + .../labelpattern/ResolveDuplicateLabelDialog.java | 14 +++++++++----- .../gui/labelpattern/SearchFixDuplicateLabels.java | 4 +++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f751d8718da2..35887f34c003 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - [#1485](https://github.com/JabRef/jabref/issues/1485): Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography - [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view - Updated German translation +- When resolving duplicate BibTeX-keys there is now an "Ignore" button. "Cancel" and close key now quits the resolving. ### Fixed - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/ResolveDuplicateLabelDialog.java b/src/main/java/net/sf/jabref/gui/labelpattern/ResolveDuplicateLabelDialog.java index 432905a8e3db..7712be898b6a 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/ResolveDuplicateLabelDialog.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/ResolveDuplicateLabelDialog.java @@ -51,6 +51,7 @@ class ResolveDuplicateLabelDialog { private final JDialog diag; private final List cbs = new ArrayList<>(); private boolean okPressed; + private boolean cancelPressed; private static final String LAYOUT = "\\bibtextype\\begin{bibtexkey} (\\bibtexkey)\\end{bibtexkey}
    \n" + "\\begin{author} \\format[HTMLChars,AuthorAbbreviator,AuthorAndsReplacer]{\\author}
    \\end{author}\n" + @@ -78,15 +79,10 @@ public ResolveDuplicateLabelDialog(BasePanel panel, String key, List e int row = 3; for (BibEntry entry : entries) { JCheckBox cb = new JCheckBox(Localization.lang("Generate BibTeX key"), !first); - //JPanel pan = new JPanel(); - //pan.setLayout(new BorderLayout()); - //pan.add(cb, BorderLayout.NORTH); - //cb.add(new JPanel(), BorderLayout.CENTER); b.appendRows("1dlu, p"); b.add(cb).xy(1, row); PreviewPanel pp = new PreviewPanel(null, entry, null, ResolveDuplicateLabelDialog.LAYOUT); pp.setPreferredSize(new Dimension(800, 90)); - //pp.setBorder(BorderFactory.createEtchedBorder()); b.add(new JScrollPane(pp)).xy(3, row); row += 2; cbs.add(cb); @@ -97,6 +93,8 @@ public ResolveDuplicateLabelDialog(BasePanel panel, String key, List e bb.addGlue(); JButton ok = new JButton(Localization.lang("OK")); bb.addButton(ok); + JButton ignore = new JButton(Localization.lang("Ignore")); + bb.addButton(ignore); JButton cancel = new JButton(Localization.lang("Cancel")); bb.addButton(cancel); bb.addGlue(); @@ -112,11 +110,13 @@ public ResolveDuplicateLabelDialog(BasePanel panel, String key, List e diag.dispose(); }); + ignore.addActionListener(e -> diag.dispose()); AbstractAction closeAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { + cancelPressed = true; diag.dispose(); } }; @@ -152,4 +152,8 @@ public void show() { diag.setLocationRelativeTo(diag.getParent()); diag.setVisible(true); } + + public boolean isCancelPressed() { + return cancelPressed; + } } diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java b/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java index 80d59d04b1ab..93031edd9a25 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java @@ -47,7 +47,7 @@ public SearchFixDuplicateLabels(BasePanel panel) { @Override public void run() { - // Find all multiple occurences of BibTeX keys. + // Find all multiple occurrences of BibTeX keys. dupes = new HashMap<>(); Map foundKeys = new HashMap<>(); @@ -99,6 +99,8 @@ public void update() { toGenerateFor.add(dupeEntry.getValue().get(i)); } } + } else if (rdld.isCancelPressed()) { + break; } } From 499a35520d85a259ef9aa85f05829fe17afe9984 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Thu, 7 Jul 2016 10:25:50 +0200 Subject: [PATCH 183/268] Quick fix for #1551 --- src/main/java/net/sf/jabref/gui/groups/GroupSelector.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 38af9d100b23..715001ef3a66 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -722,7 +722,8 @@ public void componentClosing() { private void setGroups(GroupTreeNode groupsRoot) { this.groupsRoot = new GroupTreeNodeViewModel(groupsRoot); - this.groupsRoot.subscribeToDescendantChanged(groupsTreeModel::nodeStructureChanged); + // refactor notice: groupsTreeModel::nodeStructureChanged cannot be used, because an NPE will be risen if no groupsTreeModel exists + this.groupsRoot.subscribeToDescendantChanged(source -> groupsTreeModel.nodeStructureChanged(source)); groupsTreeModel = new DefaultTreeModel(this.groupsRoot); groupsTree.setModel(groupsTreeModel); if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_EXPAND_TREE)) { From 28d43875083df6d7fdbca201d7ec8390301bbbd0 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 8 Jul 2016 10:26:44 +0200 Subject: [PATCH 184/268] Added content-type heading for HTML export fixing #1484 (#1545) --- CHANGELOG.md | 1 + src/main/resources/resource/layout/html.begin.layout | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35887f34c003..6f2693965b48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1482](https://github.com/JabRef/jabref/issues/1482): Correct number of matched entries is displayed for refining subgroups - Fixed [#1444](https://github.com/JabRef/jabref/issues/1444): Implement getExtension and getDescription for importers. - Fixed [#1507](https://github.com/JabRef/jabref/issues/1507): Keywords are now separated by the delimiter specified in the preferences +- Fixed [#1484](https://github.com/JabRef/jabref/issues/1484): HTML export handles some UTF characters wrong ### Removed diff --git a/src/main/resources/resource/layout/html.begin.layout b/src/main/resources/resource/layout/html.begin.layout index bc9fee58f117..77417a905422 100644 --- a/src/main/resources/resource/layout/html.begin.layout +++ b/src/main/resources/resource/layout/html.begin.layout @@ -1,8 +1,9 @@ -
    + JabRef Output + -
    + From efde8eee9870d2ee489edb12f7a7843cf1a7e765 Mon Sep 17 00:00:00 2001 From: Matthias Geiger Date: Fri, 8 Jul 2016 11:57:14 +0200 Subject: [PATCH 185/268] Link to forum (#1555) * add general open browser action * use general open browser action and add forum --- CHANGELOG.md | 1 + .../java/net/sf/jabref/gui/IconTheme.java | 1 + .../java/net/sf/jabref/gui/JabRefFrame.java | 12 +++-- .../jabref/gui/actions/OpenBrowserAction.java | 49 +++++++++++++++++++ .../jabref/gui/menus/help/DonateAction.java | 42 ---------------- .../gui/menus/help/ForkMeOnGitHubAction.java | 40 --------------- src/main/resources/l10n/JabRef_da.properties | 2 + src/main/resources/l10n/JabRef_de.properties | 2 + src/main/resources/l10n/JabRef_en.properties | 1 + src/main/resources/l10n/JabRef_es.properties | 2 + src/main/resources/l10n/JabRef_fa.properties | 2 + src/main/resources/l10n/JabRef_fr.properties | 2 + src/main/resources/l10n/JabRef_in.properties | 2 + src/main/resources/l10n/JabRef_it.properties | 2 + src/main/resources/l10n/JabRef_ja.properties | 2 + src/main/resources/l10n/JabRef_nl.properties | 2 + src/main/resources/l10n/JabRef_no.properties | 2 + .../resources/l10n/JabRef_pt_BR.properties | 2 + src/main/resources/l10n/JabRef_ru.properties | 2 + src/main/resources/l10n/JabRef_sv.properties | 2 + src/main/resources/l10n/JabRef_tr.properties | 2 + src/main/resources/l10n/JabRef_vi.properties | 2 + src/main/resources/l10n/JabRef_zh.properties | 2 + src/main/resources/l10n/Menu_da.properties | 2 + src/main/resources/l10n/Menu_de.properties | 2 + src/main/resources/l10n/Menu_en.properties | 1 + src/main/resources/l10n/Menu_es.properties | 2 + src/main/resources/l10n/Menu_fa.properties | 2 + src/main/resources/l10n/Menu_fr.properties | 2 + src/main/resources/l10n/Menu_in.properties | 2 + src/main/resources/l10n/Menu_it.properties | 2 + src/main/resources/l10n/Menu_ja.properties | 2 + src/main/resources/l10n/Menu_nl.properties | 2 + src/main/resources/l10n/Menu_no.properties | 2 + src/main/resources/l10n/Menu_pt_BR.properties | 2 + src/main/resources/l10n/Menu_ru.properties | 2 + src/main/resources/l10n/Menu_sv.properties | 2 + src/main/resources/l10n/Menu_tr.properties | 2 + src/main/resources/l10n/Menu_vi.properties | 2 + src/main/resources/l10n/Menu_zh.properties | 2 + 40 files changed, 125 insertions(+), 86 deletions(-) create mode 100644 src/main/java/net/sf/jabref/gui/actions/OpenBrowserAction.java delete mode 100644 src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java delete mode 100644 src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f2693965b48..0728942fe90a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view - Updated German translation - When resolving duplicate BibTeX-keys there is now an "Ignore" button. "Cancel" and close key now quits the resolving. +- The [online forum](http://discourse.jabref.org/) is now directly accessible via the "Help" menu ### Fixed - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them diff --git a/src/main/java/net/sf/jabref/gui/IconTheme.java b/src/main/java/net/sf/jabref/gui/IconTheme.java index 5dd4fbf130bd..6b2ea150da39 100644 --- a/src/main/java/net/sf/jabref/gui/IconTheme.java +++ b/src/main/java/net/sf/jabref/gui/IconTheme.java @@ -170,6 +170,7 @@ public enum JabRefIcon { CASE_SENSITIVE("\uf02c"), /* css: mdi-alphabetical */ REG_EX("\uf451"), /*css: mdi-regex */ CONSOLE("\uf18d"), /*css: console */ + FORUM("\uF28C"), /* css: forum */ // STILL MISSING: GROUP_REGULAR("\uF4E6", Color.RED); diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 3dc1dac95ca0..77082a8976ba 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -92,6 +92,7 @@ import net.sf.jabref.gui.actions.NewDatabaseAction; import net.sf.jabref.gui.actions.NewEntryAction; import net.sf.jabref.gui.actions.NewSubDatabaseAction; +import net.sf.jabref.gui.actions.OpenBrowserAction; import net.sf.jabref.gui.actions.SearchForUpdateAction; import net.sf.jabref.gui.actions.SortTabsAction; import net.sf.jabref.gui.dbproperties.DatabasePropertiesDialog; @@ -108,8 +109,6 @@ import net.sf.jabref.gui.menus.ChangeEntryTypeMenu; import net.sf.jabref.gui.menus.FileHistoryMenu; import net.sf.jabref.gui.menus.RightClickMenu; -import net.sf.jabref.gui.menus.help.DonateAction; -import net.sf.jabref.gui.menus.help.ForkMeOnGitHubAction; import net.sf.jabref.gui.openoffice.OpenOfficePanel; import net.sf.jabref.gui.preftabs.PreferencesDialog; import net.sf.jabref.gui.util.FocusRequester; @@ -214,8 +213,12 @@ public class JabRefFrame extends JFrame implements OutputPrinter { private final AbstractAction newBibtexDatabaseAction = new NewDatabaseAction(this, BibDatabaseMode.BIBTEX); private final AbstractAction newBiblatexDatabaseAction = new NewDatabaseAction(this, BibDatabaseMode.BIBLATEX); private final AbstractAction newSubDatabaseAction = new NewSubDatabaseAction(this); - private final AbstractAction forkMeOnGitHubAction = new ForkMeOnGitHubAction(); - private final AbstractAction donationAction = new DonateAction(); + private final AbstractAction forkMeOnGitHubAction = new OpenBrowserAction("https://github.com/JabRef/jabref", + Localization.menuTitle("Fork me on GitHub"), Localization.lang("Opens JabRef's GitHub page"), IconTheme.JabRefIcon.GITHUB.getSmallIcon(), IconTheme.JabRefIcon.GITHUB.getIcon()); + private final AbstractAction donationAction = new OpenBrowserAction("https://github.com/JabRef/jabref/wiki/Donations", + Localization.menuTitle("Donate to JabRef"), Localization.lang("Donate to JabRef"), IconTheme.JabRefIcon.DONATE.getSmallIcon(), IconTheme.JabRefIcon.DONATE.getIcon()); + private final AbstractAction openForumAction = new OpenBrowserAction("http://discourse.jabref.org/", + Localization.menuTitle("Online help forum"), Localization.lang("Online help forum"), IconTheme.JabRefIcon.FORUM.getSmallIcon(), IconTheme.JabRefIcon.FORUM.getIcon()); private final AbstractAction help = new HelpAction(Localization.menuTitle("Online help"), Localization.lang("Online help"), HelpFiles.CONTENTS, Globals.getKeyPrefs().getKey(KeyBinding.HELP)); private final AbstractAction about = new AboutAction(Localization.menuTitle("About JabRef"), aboutDiag, @@ -1349,6 +1352,7 @@ private void fillMenu() { mb.add(options); helpMenu.add(help); + helpMenu.add(openForumAction); helpMenu.addSeparator(); helpMenu.add(errorConsole); helpMenu.addSeparator(); diff --git a/src/main/java/net/sf/jabref/gui/actions/OpenBrowserAction.java b/src/main/java/net/sf/jabref/gui/actions/OpenBrowserAction.java new file mode 100644 index 000000000000..1887303e93e6 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/actions/OpenBrowserAction.java @@ -0,0 +1,49 @@ +package net.sf.jabref.gui.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; + +import net.sf.jabref.gui.desktop.JabRefDesktop; + +public class OpenBrowserAction extends AbstractAction { + + private final String urlToOpen; + + /** + * OpenBrowserAction without icons - only to be used for menus + * + * @param urlToOpen URL string of an URL to be shown in the default web browser + * @param menuTitle title of the menu entry; should already be localized + * @param description description shown in a tooltip hovering over the menu/icon bar entry; should already be localized + */ + public OpenBrowserAction(String urlToOpen, String menuTitle, String description) { + super(menuTitle); + this.urlToOpen = urlToOpen; + putValue(Action.SHORT_DESCRIPTION, description); + } + + /** + * OpenBrowserAction with icons + * + * @param urlToOpen URL string of an URL to be shown in the default web browser + * @param menuTitle title of the menu entry; should already be localized + * @param description description shown in a tooltip hovering over the menu/icon bar entry; should already be localized + * @param smallIcon smallIcon to be shown in the menus + * @param largeIcon larger icon to be shown in the icon bar + */ + public OpenBrowserAction(String urlToOpen, String menuTitle, String description, Icon smallIcon, Icon largeIcon) { + super(menuTitle, smallIcon); + this.urlToOpen = urlToOpen; + putValue(Action.SHORT_DESCRIPTION, description); + putValue(Action.LARGE_ICON_KEY, largeIcon); + } + + @Override + public void actionPerformed(ActionEvent e) { + JabRefDesktop.openBrowserShowPopup(urlToOpen); + } + +} diff --git a/src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java b/src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java deleted file mode 100644 index 9727187acb2f..000000000000 --- a/src/main/java/net/sf/jabref/gui/menus/help/DonateAction.java +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (C) 2015 Oliver Kopp - 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.menus.help; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; -import javax.swing.Action; - -import net.sf.jabref.gui.IconTheme; -import net.sf.jabref.gui.desktop.JabRefDesktop; -import net.sf.jabref.logic.l10n.Localization; - -public class DonateAction extends AbstractAction { - - private static final String DONATION_LINK = "https://github.com/JabRef/jabref/wiki/Donations"; - - public DonateAction() { - super(Localization.menuTitle("Donate to JabRef")); - putValue(Action.SHORT_DESCRIPTION, Localization.lang("Donate to JabRef")); - putValue(Action.SMALL_ICON, IconTheme.JabRefIcon.DONATE.getSmallIcon()); - putValue(Action.LARGE_ICON_KEY, IconTheme.JabRefIcon.DONATE.getIcon()); - } - - @Override - public void actionPerformed(ActionEvent e) { - JabRefDesktop.openBrowserShowPopup(DONATION_LINK); - } -} diff --git a/src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java b/src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java deleted file mode 100644 index b474cd948894..000000000000 --- a/src/main/java/net/sf/jabref/gui/menus/help/ForkMeOnGitHubAction.java +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2015 Oliver Kopp - 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.menus.help; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; -import javax.swing.Action; - -import net.sf.jabref.gui.IconTheme; -import net.sf.jabref.gui.desktop.JabRefDesktop; -import net.sf.jabref.logic.l10n.Localization; - -@SuppressWarnings("serial") -public class ForkMeOnGitHubAction extends AbstractAction { - - public ForkMeOnGitHubAction() { - super(Localization.menuTitle("Fork me on GitHub"), IconTheme.JabRefIcon.GITHUB.getSmallIcon()); - putValue(Action.SHORT_DESCRIPTION, Localization.lang("Opens JabRef's GitHub page")); - putValue(Action.LARGE_ICON_KEY, IconTheme.JabRefIcon.GITHUB.getIcon()); - } - - @Override - public void actionPerformed(ActionEvent e) { - JabRefDesktop.openBrowserShowPopup("https://github.com/JabRef/jabref"); - } -} diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 261de61d3a6c..d30a8dd7d5bf 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1703,3 +1703,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 54e67e42cb1e..5b7fefc63192 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2420,3 +2420,5 @@ Latest_version=Neueste_Version Please_open_%0_manually.=Bitte_öffnen_Sie_%0_manuell. The_link_has_been_copied_to_the_clipboard.=Der_Link_wurde_in_die_Zwischenablage_kopiert. + +Online_help_forum=Online-Hilfeforum diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 66fbed6f8d33..a85ebc531260 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2274,3 +2274,4 @@ To_see_what's_new_view_the_changelog.=To_see_what's_new_view_the_changelog. A_new_version_of_JabRef_has_been_released.=A_new_version_of_JabRef_has_been_released. JabRef_is_up-to-date.=JabRef_is_up-to-date. Latest_version=Latest_version +Online_help_forum=Online_help_forum \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index d68b3cadd23f..9be684ebbdbb 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1605,3 +1605,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index ea5d7e69556e..6a2a4b8f2a4d 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2391,3 +2391,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index d858300eb70d..d7b634d6a445 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1649,3 +1649,5 @@ Latest_version=Version_la_plus_récente Please_open_%0_manually.=Ouvrez_%0_manuellement,_SVP. The_link_has_been_copied_to_the_clipboard.=Le_lien_a_été_copié_dans_le_presse-papiers. + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 60d981a62328..4f57a4b8ecf3 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1624,3 +1624,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 0e320e3c78ac..fa88dc92320f 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1724,3 +1724,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 8b28b96171a2..066320369067 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2369,3 +2369,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 0fef6105649f..2cb522bb728a 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2400,3 +2400,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 9606110dfbc5..903c290d7316 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2796,3 +2796,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 8538273175e6..c6b952611447 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1618,3 +1618,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 66bc9b7514e0..0a74a044f182 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2368,3 +2368,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 7f3f60ac4105..c18984abb366 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1561,3 +1561,5 @@ Latest_version=Senaste_version Please_open_%0_manually.=Öppna_%0_för_hand. The_link_has_been_copied_to_the_clipboard.=Länken_har_kopierats_till_urklipp. + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index fed34c818887..ad379f6ffc13 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1637,3 +1637,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index a41d1408c3a1..3fc4d0073ca3 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2392,3 +2392,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index f258102b62c1..a1357497fb60 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1631,3 +1631,5 @@ Latest_version= Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_da.properties b/src/main/resources/l10n/Menu_da.properties index 8a7156074de5..5ef474690054 100644 --- a/src/main/resources/l10n/Menu_da.properties +++ b/src/main/resources/l10n/Menu_da.properties @@ -110,3 +110,5 @@ Quality=Kvalitet New_%0_database=Ny_%0-database Disable_highlight_groups_matching_entries=Deaktiver_fremhævningen_af_grupperede_indgange + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_de.properties b/src/main/resources/l10n/Menu_de.properties index b30a5b1593a1..454b78efda51 100644 --- a/src/main/resources/l10n/Menu_de.properties +++ b/src/main/resources/l10n/Menu_de.properties @@ -207,3 +207,5 @@ Quality=Qualität New_%0_database=Neue_%0_Datenbank Disable_highlight_groups_matching_entries=Keine_Gruppen_hervorheben + +Online_help_forum=Online-Hilfeforum diff --git a/src/main/resources/l10n/Menu_en.properties b/src/main/resources/l10n/Menu_en.properties index b6aed64519fb..ff43855f1381 100644 --- a/src/main/resources/l10n/Menu_en.properties +++ b/src/main/resources/l10n/Menu_en.properties @@ -125,3 +125,4 @@ Delete_entry=Delete_entry Check_integrity=Check_integrity Quality=Quality +Online_help_forum=Online_help_forum \ No newline at end of file diff --git a/src/main/resources/l10n/Menu_es.properties b/src/main/resources/l10n/Menu_es.properties index 13131756b826..ff70ea28bcca 100644 --- a/src/main/resources/l10n/Menu_es.properties +++ b/src/main/resources/l10n/Menu_es.properties @@ -136,3 +136,5 @@ Quality=Calidad New_%0_database=Nueva_base_de_datos_%0 Disable_highlight_groups_matching_entries=Inhabilitar_grupos_destacados_coincidentes_con_las_entradas + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_fa.properties b/src/main/resources/l10n/Menu_fa.properties index 68777c74dd21..e573241c54f2 100644 --- a/src/main/resources/l10n/Menu_fa.properties +++ b/src/main/resources/l10n/Menu_fa.properties @@ -134,3 +134,5 @@ New_%0_database=پایگاه‌داده‌ی_%0_جدید Disable_highlight_groups_matching_entries=گروه‌های_مشخص_شده‌ی_مطابق_با_مدخل‌ها_را_حذف_کن + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_fr.properties b/src/main/resources/l10n/Menu_fr.properties index bdd5fa914b83..c96c38c1bf64 100644 --- a/src/main/resources/l10n/Menu_fr.properties +++ b/src/main/resources/l10n/Menu_fr.properties @@ -122,3 +122,5 @@ Quality=Qualité New_%0_database=Nouvelle_base_%0 Disable_highlight_groups_matching_entries=Désactiver_le_surlignement_des_groupes_correspondant_à_des_entrées + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_in.properties b/src/main/resources/l10n/Menu_in.properties index 79027f680c61..e5312183bff0 100644 --- a/src/main/resources/l10n/Menu_in.properties +++ b/src/main/resources/l10n/Menu_in.properties @@ -107,3 +107,5 @@ Quality=Kualitas New_%0_database=Basisdata_%0_baru Disable_highlight_groups_matching_entries=Pewarnaan_grup_entri_yang_sesuai_tidak_aktif + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_it.properties b/src/main/resources/l10n/Menu_it.properties index a5f4ab4a335d..6d543fa66b51 100644 --- a/src/main/resources/l10n/Menu_it.properties +++ b/src/main/resources/l10n/Menu_it.properties @@ -128,3 +128,5 @@ Quality=Qualità New_%0_database=Nuovo_database_%0 Disable_highlight_groups_matching_entries=Disattiva_l'evidenziazione_dei_gruppi_corrispondenti_alle_voci + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_ja.properties b/src/main/resources/l10n/Menu_ja.properties index 4a2b1cdd9e16..375201b80c5e 100644 --- a/src/main/resources/l10n/Menu_ja.properties +++ b/src/main/resources/l10n/Menu_ja.properties @@ -135,3 +135,5 @@ Quality=品質 New_%0_database=新しい%0データベース Disable_highlight_groups_matching_entries=項目に一致するグループの着色を無効化 + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_nl.properties b/src/main/resources/l10n/Menu_nl.properties index eced839c6fb2..88af69db2173 100644 --- a/src/main/resources/l10n/Menu_nl.properties +++ b/src/main/resources/l10n/Menu_nl.properties @@ -215,3 +215,5 @@ Quality=Kwaliteit New_%0_database=Nieuwe_%0_database Disable_highlight_groups_matching_entries=Overeenkomende_groepen_van_invoer_oplichten_uitschakelen + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_no.properties b/src/main/resources/l10n/Menu_no.properties index 6386f1c87bb5..15fa4a86254e 100644 --- a/src/main/resources/l10n/Menu_no.properties +++ b/src/main/resources/l10n/Menu_no.properties @@ -128,3 +128,5 @@ Quality=Kvalitet New_%0_database=Ny %0-database Disable_highlight_groups_matching_entries=Deaktiver markerte samsvarende oppføringer + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_pt_BR.properties b/src/main/resources/l10n/Menu_pt_BR.properties index b9fed7d16c8c..da7b8f6ed1e0 100644 --- a/src/main/resources/l10n/Menu_pt_BR.properties +++ b/src/main/resources/l10n/Menu_pt_BR.properties @@ -109,3 +109,5 @@ Quality=Qualidade New_%0_database=%0_novas_bases_de_dados Disable_highlight_groups_matching_entries=Desabilitar_destacar_grupos_contendo_referências + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_ru.properties b/src/main/resources/l10n/Menu_ru.properties index 7abe93f0012c..4f72effcec18 100644 --- a/src/main/resources/l10n/Menu_ru.properties +++ b/src/main/resources/l10n/Menu_ru.properties @@ -132,3 +132,5 @@ Quality=Качество New_%0_database=Новая_база_данных_%0 Disable_highlight_groups_matching_entries=Отключить_выделение_групп,_соответствующих_выделенным_записям + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_sv.properties b/src/main/resources/l10n/Menu_sv.properties index 59f7c2cff29b..e0d6c62cc6ab 100644 --- a/src/main/resources/l10n/Menu_sv.properties +++ b/src/main/resources/l10n/Menu_sv.properties @@ -98,3 +98,5 @@ Groups=&Grupper Delete_entry=Radera_post Check_integrity=Testa_&integriteten Quality=&Kvalitet + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_tr.properties b/src/main/resources/l10n/Menu_tr.properties index ed1430ae83b9..a3ac7436fc54 100644 --- a/src/main/resources/l10n/Menu_tr.properties +++ b/src/main/resources/l10n/Menu_tr.properties @@ -111,3 +111,5 @@ Quality=Kalite New_%0_database=Yeni_%0_veri_tabanı Disable_highlight_groups_matching_entries=Vurgulu_gruplarla_eşleşen_girdileri_etkisizleştir + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_vi.properties b/src/main/resources/l10n/Menu_vi.properties index afb2304aff39..40e991675dd1 100644 --- a/src/main/resources/l10n/Menu_vi.properties +++ b/src/main/resources/l10n/Menu_vi.properties @@ -134,3 +134,5 @@ Quality= New_%0_database= Disable_highlight_groups_matching_entries= + +Online_help_forum= diff --git a/src/main/resources/l10n/Menu_zh.properties b/src/main/resources/l10n/Menu_zh.properties index 0803d0db7c39..a4db4dbcc012 100644 --- a/src/main/resources/l10n/Menu_zh.properties +++ b/src/main/resources/l10n/Menu_zh.properties @@ -133,3 +133,5 @@ Quality=质量 New_%0_database=新建_%0_数据库 Disable_highlight_groups_matching_entries=禁用高亮显示包含选中记录的分组 + +Online_help_forum= From 8209539ff8dfcedb8ef20bc7f2502fb116a1ed16 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 8 Jul 2016 13:44:18 +0200 Subject: [PATCH 186/268] Swedish translations (#1556) --- src/main/resources/l10n/JabRef_sv.properties | 166 +++++++++---------- src/main/resources/l10n/Menu_sv.properties | 2 +- 2 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index c18984abb366..8f18ec74669e 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -37,9 +37,9 @@ Accept_change=Acceptera_ändring Accepting_the_change_replaces_the_complete_groups_tree_with_the_externally_modified_groups_tree.=Om_ändringarna_accepteras_så_kommer_hela_gruppträdet_att_ersättas_av_det_externt_ändrade_gruppträdet. Action=Händelse Add=Lägg_till -Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.= -Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path.= -Add_entry_selection_to_this_group= +Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.=Lägg_till_en_(kompilerad)_ImportFormat-klass_från_en_zip-fil. +Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path.=Lägg_till_en_(kompilerad)_ImportFormat-klass_från_en_sökväg_till_en_klass. +Add_entry_selection_to_this_group=Lägg_till_valda_poster_till_denna_grupp Add_from_folder=Lägg_till_från_mapp Add_from_jar=Lägg_till_från_jar-fil Add_group=Lägg_till_grupp @@ -60,7 +60,7 @@ Adds_{}_brackets_around_acronyms,_month_names_and_countries_to_preserve_their_ca Advanced=Avancerad Advanced_search_active.=Avancerad_sökning_aktiv. All_entries=Alla_poster -All_entries_of_this_type_will_be_declared_typeless._Continue?= +All_entries_of_this_type_will_be_declared_typeless._Continue?=Alla_poster_av_denna_typ_kommer_att_bli_typlösa._Fortsätt? All_fields=Alla_fält All_key_bindings_will_be_reset_to_their_defaults.=Alla_tangentbordsbindingar_kommer_att_återställas_till_standardvärden. All_subgroups_(recursively)=Alla_undergrupper_(rekursivt) @@ -72,8 +72,8 @@ An_Error_occurred_while_fetching_from_ADS_(%0)\:= An_Error_occurred_while_parsing_abstract=Ett_fel_inträffade_när_sammanfattningen_tolkades An_Exception_occurred_while_accessing_'%0'= An_SAXException_occurred_while_parsing_'%0'\:= -An_autosave_file_was_found_for_this_database._This_could_indicate_that_JabRef_didn't_shut_down_cleanly_last_time_the_file_was_used.= -Appearance= +An_autosave_file_was_found_for_this_database._This_could_indicate_that_JabRef_didn't_shut_down_cleanly_last_time_the_file_was_used.=En_automatiskt_sparad_fil_hittades_för_databasen._Det_kan_betyda_att_JabRef_inte_avslutades_korrekt_senaste_gången_databasen_användes. +Appearance=Utseende Append=Lägg_till Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Lägg_till_innehåll_från_en_BibTeX-databas_till_den_nu_aktiva_databasen Append_database=Lägg_till_databas @@ -91,8 +91,8 @@ Assigned_1_entry_to_group_"%0".=Tilldelade_en_post_till_gruppen_"%0". Attach_URL=Lägg_till_URL Attach_file=Lägg_till_fil Attempt_to_automatically_set_file_links_for_your_entries._Automatically_setting_works_if_a_file_in_your_file_directory
    or_a_subdirectory_is_named_identically_to_an_entry's_BibTeX_key,_plus_extension.= -Attempting_SQL_export...=Försöker_SQL-export -Attempting_SQL_import...=Försöker_SQL-import +Attempting_SQL_export...=Försöker_exportera_till_SQL-databas... +Attempting_SQL_import...=Försöker_importera_från_SQL-databas... Attention\:_Password_is_stored_in_plain_text\!=OBS\!_Lösenordet_sparas_i_klartext\! Auto-generating_PDF-Names_does_not_support_undo._Continue?=Du_kan_inte_ångra_automatisk_generering_av_PDF-namn._Fortsätt? Auto=Automatiskt @@ -108,18 +108,18 @@ Autogenerate_BibTeX_keys=Generera_BibTeX-nycklar_automatiskt Autogenerate_PDF_Names=Generera_PDF-namn_automatiskt Autolink_files_with_names_starting_with_the_BibTeX_key=Länka_filer_vars_namn_börjar_med_BibTeX-nyckeln_automatiskt Autolink_only_files_that_match_the_BibTeX_key=Länka_bara_filer_vars_namn_är_BibTeX-nyckeln_automatiskt -Automatically_assign_new_entry_to_selected_groups= +Automatically_assign_new_entry_to_selected_groups=Tilldela_automatiskt_nya_poster_till_valda_grupper Automatically_create_groups=Skapa_grupper_automatiskt Automatically_create_groups_for_database.=Skapa_grupper_automatiskt_för_databasen. Automatically_created_groups=Skapade_grupper_automatiskt -Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups= +Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Göm_automatiskt_gruppgränssnittet_när_en_databas_som_inte_innehåller_grupper_blir_aktiv Automatically_open_browse_dialog_when_creating_new_file_link= Automatically_open_folders_of_attached_files= Automatically_remove_exact_duplicates=Ta_bort_exakta_dubbletter_automatiskt Automatically_set_file_links=Skapa_fillänkar_automatiskt Automatically_set_file_links_for_this_entry=Skapa_fillänkar_automatiskt_för_denna_post Automatically_setting_file_links=Skapar_fillänkar_automatiskt -Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups= +Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Visa_automatiskt_gruppgränssnittet_när_en_databas_som_innehåller_grupper_blir_aktiv Automatically_sync_bibliography_when_inserting_citations=Synkronisera_bibliografin_automatiskt_när_citeringar_infogas Autosave=Automatisk_sparning Autosave_interval_(minutes)=Intervall_för_automatisk_sparning_(minuter) @@ -141,17 +141,17 @@ Browse=Bläddra Built-in_journal_list=Inbyggd_tidskriftslista Cancel=Avbryt Canceled_merging_entries=Avbröt_sammanslagning_av_poster -Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?= +Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Kan_inte_lägga_till_poster_till_grupp_utan_att_generera_nycklar._Generera_nycklar_nu? Cannot_delete_file=Kan_inte_radera_fil Cannot_get_info_based_on_given_DOI\:_%0= Cannot_merge_this_change=Kan_inte_införa_den_här_ändringen -Cannot_move_group_"%0"_down.= -Cannot_move_group_"%0"_left.= -Cannot_move_group_"%0"_right.= -Cannot_move_group_"%0"_up.= -Cannot_use_port_%0_for_remote_operation;_another_application_may_be_using_it._Try_specifying_another_port.= +Cannot_move_group_"%0"_down.=Kan_inte_flytta_gruppen_"%0"_nedåt. +Cannot_move_group_"%0"_left.=Kan_inte_flytta_gruppen_"%0"_till_vänster. +Cannot_move_group_"%0"_right.=Kan_inte_flytta_gruppen_"%0"_till_höger. +Cannot_move_group_"%0"_up.=Kan_inte_flytta_gruppen_"%0"_uppåt. +Cannot_use_port_%0_for_remote_operation;_another_application_may_be_using_it._Try_specifying_another_port.=Kan_inte_använda_port_"%0"_för_fjärråtkomst;_ett_annat_program_kanske_använder_den._Försök_med_en_annan_port. Case_sensitive=Shiftlägeskänlig -Change_case= +Change_case=Ändra_shiftläge Change_entry_type=Ändra_posttyp Change_file_type=Ändra_filtyp Change_of_Grouping_Method= @@ -171,7 +171,7 @@ Choose_Directory=Välj_mapp Choose_OpenOffice/LibreOffice_executable=Välj_OpenOffice/LibreOffice-program Choose_pattern=Välj_mönster Choose_the_URL_to_download.=Välj_URL_att_ladda_ned. -Choose_the_source_for_the_metadata_import= +Choose_the_source_for_the_metadata_import=Välj_källa_för_metadata-import Citation=Citering Cite=Referera Cite_command=Citeringskommando @@ -199,7 +199,7 @@ Close_All=Stäng_alla Close_Others=Stäng_andra Close_database=Stäng_databas Close_dialog=Stäng_dialog -Close_entry_editor= +Close_entry_editor=Stäng_posteditor Close_the_current_database=Stäng_aktuell_databas Close_window=Stäng_fönster Closed_database=Stängde_databasen @@ -218,7 +218,7 @@ Connected_to_document=Ansluten_till_dokument Connecting=Ansluter Connection_lost=Tappade_anslutning Connection_to_OpenOffice/LibreOffice_has_been_lost._Please_make_sure_OpenOffice/LibreOffice_is_running,_and_try_to_reconnect.=Anslutningen_till_OpenOffice/LibreOffice_försvann._Se_till_att_OpenOffice/LibreOffice_körs_och_anslut_på_nytt. -Contained_in= +Contained_in=Finns_i Content=Innehåll Continue?=Fortsätt? Convert=Konvertera @@ -262,7 +262,7 @@ Could_not_open_link=Kunde_inte_öppna_länk Could_not_paste_entry_as_text\:=Kunde_inte_klista_in_post_so_text\: Could_not_print_preview=Kunde_inte_skriva_ut_postvisning Could_not_resolve_BibTeX_entry_for_citation_marker_'%0'.=Kunde_inte_hitta_en_BibTeX-post_för_referensmarkören_'%0'. -Could_not_run_the_'vim'_program.= +Could_not_run_the_'vim'_program.=Kunde_inte_köra_'vim'. Could_not_run_the_gnuclient/emacsclient_program._Make_sure_you_have_the_emacsclient/gnuclient_program_installed_and_available_in_the_PATH.= Could_not_save,_file_locked_by_another_JabRef_instance.=Kunde_inte_spara._Filen_låst_av_en_annan_JabRef-instans. Could_not_save_file.=Kunde_inte_spara_fil. @@ -292,7 +292,7 @@ Database_protection=Databasskydd Date_format=Datumformat Decrease_table_font_size=Minska_typsnittsstorlek_för_tabellen Default=Standard -Default_PDF_file_link_action= +Default_PDF_file_link_action=Standardhändelse_för_PDF-fil Default_bibliography_mode=Standardläge_för_databas Default_encoding=Standardteckenkodning Default_grouping_field=Standardfält_för_gruppering @@ -317,16 +317,16 @@ Description=Beskrivning Deselect_all= Deselect_all_duplicates= Directories=Mappar -Disable_entry_editor_when_multiple_entries_are_selected= +Disable_entry_editor_when_multiple_entries_are_selected=Inaktivera_posteditorn_när_flera_poster_är_valda Disable_highlight_groups_matching_entries=Avvaktivera_framhävandet_av_grupper_som_matchar_poster Disable_this_confirmation_dialog=Avaktivera_denna_bekräftelsedialog Discard_changes=Ignorera_ändringar -Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.= +Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Visa_alla_poster_som_ingår_i_en_eller_flera_valda_grupper. Display_all_error_messages=Visa_alla_felmeddelanden -Display_help_on_command_line_options= +Display_help_on_command_line_options=Visa_hjälp_för_kommandoradsalternativ Display_keywords_appearing_in_ALL_entries=Visa_nyckelord_som_finns_i_ALLA_poster Display_keywords_appearing_in_ANY_entry=Visa_nyckelord_som_finns_i_NÅGON_post -Display_only_entries_belonging_to_all_selected_groups.= +Display_only_entries_belonging_to_all_selected_groups.=Visa_bara_poster_som_ingår_i_alla_valda_grupper. Display_version=Visa_version Displaying_no_groups=Visar_inga_grupper Do_not_abbreviate_names=Förkorta_ej_namn @@ -372,32 +372,32 @@ Edit_group=Ändra_grupp Edit_journal=Ändra_tidsskrift Edit_preamble=Ändra_preamble Edit_strings=Ändra_strängar -Editor_options= +Editor_options=Editoralternativ Empty_BibTeX_key=Tom_BibTeX-nyckel -Enable_save_actions= +Enable_save_actions=Aktivera_automatiska_händelser_vid_sparning Enable_special_fields=Aktivera_specialfält -Enable_word/name_autocompletion= +Enable_word/name_autocompletion=Aktivera_automatisk_komplettering_av_ord/namn Enforce_legal_characters_in_BibTeX_keys=Framtvinga_giltiga_tecken_i_BibTeX-nycklar Ensure_that_the_bibliography_is_up-to-date=Se_till_att_bibliografin_är_uppdaterad -Ensure_unique_keys_using_letters_(a,_b,_...)= -Ensure_unique_keys_using_letters_(b,_c,_...)= +Ensure_unique_keys_using_letters_(a,_b,_...)=Garantera_unika_nycklar_med_bokstäver_(a,_b,_...) +Ensure_unique_keys_using_letters_(b,_c,_...)=Garantera_unika_nycklar_med_bokstäver_(b,_c,_...) Enter_URL=Ange_URL Enter_URL_to_download=Ange_URL_att_ladda_ned Entries_added_to_an_email=Poster_lades_till_ett_epostmeddelande Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.= Entries_exported_to_clipboard=Poster_exporterades_till_urklipp -Entry_editor,_next_entry= -Entry_editor,_next_panel= -Entry_editor,_next_panel_2= -Entry_editor,_previous_entry= -Entry_editor,_previous_panel= -Entry_editor,_previous_panel_2= -Entry_editor,_store_field= -Entry_editor= -Entry_editor_active_background_color= -Entry_editor_background_color= -Entry_editor_font_color= -Entry_editor_invalid_field_color= +Entry_editor,_next_entry=Posteditor,_nästa_post +Entry_editor,_next_panel=Posteditor,_nästa_panel +Entry_editor,_next_panel_2=Posteditor,_nästa_panel_2 +Entry_editor,_previous_entry=Posteditor,_föregående_post +Entry_editor,_previous_panel=Posteditor,_föregående_panel +Entry_editor,_previous_panel_2=Posteditor,_föregående_panel_2 +Entry_editor,_store_field=Posteditor,_spara_fält +Entry_editor=Posteditor +Entry_editor_active_background_color=Bakgrundfärg_för_aktiv_post_i_posteditor +Entry_editor_background_color=Bakgrundfärg_för_posteditor +Entry_editor_font_color=Typsnittfärg_för_posteditor +Entry_editor_invalid_field_color=Färg_för_ogiltiga_fält_i_posteditor Entry_from_DOI=Post_från_DOI Entry_preview=Postvisning Entry_table=Tabell @@ -412,17 +412,17 @@ Error_downloading_file_'%0'=Fel_när_filen_'%0'_skulle laddas_ned Error_exporting_to_clipboard=Fel_vid_export_till_urklipp Error_importing_from_database=Fel_vid_import_från_databas Error_message\:=Felmeddelande\: -Error_occurred_when_parsing_entry= -Error_opening_autosave_of_'%0'._Trying_to_load_'%0'_instead.= +Error_occurred_when_parsing_entry=Fel_vid_inläsning_av_post +Error_opening_autosave_of_'%0'._Trying_to_load_'%0'_instead.=Kunde_inte_öppna_automatiskt_sparad_version_av_'%0'._Försöker_öppna_'%0'_istället. Error_opening_file=Fel_vid_öppning_av_fil -Error_opening_file_'%0'.= +Error_opening_file_'%0'.=Fel_vid_öppning_av_fil_'%0'. Error_setting_field= Error_while_downloading_file\:=Fel_vid_nedladdning_av_fil\: Error_while_fetching_from_%0= Error_while_writing= Error_writing_to_%0_file(s).= Establishing_SQL_connection...=Kopplar_upp_mot_SQL-databas... -Exceptions= +Exceptions=Undantag Existing_file=Existerande_fil Expand_all=Expandera_alla Expand_subtree=Expandera_delträd @@ -432,7 +432,7 @@ Export_sorting=Sortering_vid_export Export_entries_in_their_original_order=Exportera_poster_i_den_ursprungliga_ordningen Export_entries_ordered_as_specified=Exportera_poster_enligt_inställningar Export_in_current_table_sort_order=Exportera_poster_enligt_nuvarande_sortering -Export_name= +Export_name=Exportnamn Export_preferences=Exportera_inställningar Export_preferences_to_file=Exportera_inställningar_till_fil Export_properties=Exportera_egenskaper @@ -466,11 +466,11 @@ File_'%0'_is_already_open.=Filen_'%0'_är_redan_öppen. File_'%0'_not_found=Filen_'%0'_hittades_inte File_changed=Fil_ändrad File_directory_is_'%0'\:=Filmapp_är_'%0'\: -File_directory_is_not_set_or_does_not_exist\!= +File_directory_is_not_set_or_does_not_exist\!=Filmapp_är_inte_satt_eller_existerar_inte\! File_download=Fil_nedladdad File_exists=Filen_finns_redan File_has_been_updated_externally._What_do_you_want_to_do?=Fil_har_ändrats_utanför_JabRef._Vad_vill_du_göra? -File_is_locked_by_another_JabRef_instance.= +File_is_locked_by_another_JabRef_instance.=Filen_är_låst_av_en_annan_JabRef-instans. File_list_editor,_move_entry_down= File_list_editor,_move_entry_up= File_locked=Filen_är_låst @@ -480,7 +480,7 @@ File_permission_error=Rättighetsfel_för_fil File_rename_failed_for_%0_entries.=Döpa_om_filen_misslyckades_för_%0_poster. File_type=Filtyp File_updated_externally=Filen_uppdaterad_utanför_JabRef -Filename_format_pattern= +Filename_format_pattern=Filnamnsmönster Files_opened=Filer_öppnade Filled=Fyllde Filter=Filtrera @@ -505,11 +505,11 @@ Font_family=Typsnittsfamilj Font_preview=Typsnittsexempel Font_size=Typsnittsstorlek Font_style=Typsnittsstil -Format_String=Formattera_sträng +Format_String=Formatsträng Format_of_author_and_editor_names=Format_för_författar-_och_redaktörsnamn Format_units_by_adding_non-breaking_separators_and_keeping_the_correct_case_on_search= Format_used=Använt_format -Formatter_Name=Formatterarnamn +Formatter_Name=Formatnamn Formatter_not_found\:_%0=Hittade_ej_formatterare\:_%0 Forward=Framåt Found_%0_results.=Hittade_%0_resultat. @@ -617,7 +617,7 @@ Invalid_URL=Ogiltig_URL Invalid_date_format=Ogiltigt_datumformat Invalid_setting=Ogiltig_inställning Inverted=Omvänd -Online_help= +Online_help=Onlinehjälp JabRef_includes_a_built-in_list_of_journal_abbreviations.=JabRef_har_en_inbyggd_lista_med_tidskriftsförkortningar JabRef_no_longer_supports_'ps'_or_'pdf'_fields.
    File_links_are_now_stored_in_the_'file'_field_and_files_are_stored_in_an_external_file_directory.
    To_make_use_of_this_feature,_JabRef_needs_to_upgrade_file_links.

    = JabRef_preferences=Inställningar_för_JabRef @@ -659,15 +659,15 @@ Log=Logg Look_and_feel='Look-and-feel' Look_up_BibTeX_entries_in_all_open_databases=Leta_efter_BibTeX-poster_i_alla_öppna_databaser Look_up_BibTeX_entries_in_the_active_tab_only=Leta_bara_efter_BibTeX-poster_i_aktiv_flik -Looking_for_full_text_document...= +Looking_for_full_text_document...=Letar_efter_dokument... MIME_type=MIME-typ Main_file_directory=Huvudmapp_för_filer -Main_layout_file= -Make_paths_of_linked_files_relative_(if_possible)= +Main_layout_file=Huvudfil_för_layout +Make_paths_of_linked_files_relative_(if_possible)=Gör_sökvägen_till_länkade_filer_relativ_(om_möjligt) Make_sure_you_have_installed_OpenOffice/LibreOffice_with_Java_support.=Kontrollera_att_du_har_installerat_OpenOffice/LibreOffice_med_Java-stöd. Manage=Hantera Manage_citations=Hantera_citeringar -Manage_content_selectors= +Manage_content_selectors=Hantera_innehållsväljare Manage_custom_exports=Hantera_egna_exporterare Manage_custom_imports=Hantera_egna_importerare Manage_external_file_types=Hantera_externa_filetyper @@ -716,7 +716,7 @@ Move_up=Flytta_uppåt Moved_group_"%0".=Flyttade_grupp_"%0" Multiple_entries_selected._Do_you_want_to_change_the_type_of_all_these_to_'%0'?= Name=Namn -Name_format_used_for_autocompletion= +Name_format_used_for_autocompletion=Namnformat_för_automatisk_komplettering Name_formatter=Namnformattering Natbib_style=Natbib-stil Network=Nätverk @@ -797,7 +797,7 @@ Open_%0_file=Öppna_%0-fil Open_BibTeX_database=Öppna_BibTeX-databas Open_URL_or_DOI=Öppna_URL_eller_DOI Open_database=Öppna_databas -Open_editor_when_a_new_entry_is_created= +Open_editor_when_a_new_entry_is_created=Öppna_posteditorn_när_en_ny_post_skapats Open_file=Öppna_fil Open_folder=Öppna_mapp Open_last_edited_databases_at_startup=Öppna_senast_använda_databaser_vid_uppstart @@ -885,7 +885,7 @@ Problem_with_parsing_entry=Problem_att_tolka_post Processing_%0=Behandlar_%0 Program_output= Progress\:_%0_of_%1=Händelseförlopp\:_%0_av_%1 -Prompt_before_recovering_a_database_from_an_autosave_file= +Prompt_before_recovering_a_database_from_an_autosave_file=Meddela_innan_en_databas_återskapas_från_en_automatiskt_sparad_fil Protected_database=Skyddad_databas Proxy_requires_authentication=Proxyn_kräver_autentisering Push_to_%0=Infoga_i_%0 @@ -903,10 +903,10 @@ Read_status_read=Läst Read_status_skimmed=Skummat Really_delete_the_selected_%0_entries?=Verkligen_ta_bort_de_%0_valda_posterna? Really_delete_the_selected_entry?=Verkligen_ta_bort_den_valda_posten? -Rearrange_tabs_alphabetically_by_title= +Rearrange_tabs_alphabetically_by_title=Sortera_flikar_i_alfabetisk_ordning Rebind_C-a,_too= Rebind_C-f,_too= -Recover_from_autosave=Återställ_från_automatiskt_sparad_fil +Recover_from_autosave=Återskapa_från_automatiskt_sparad_fil Redo=Gör_igen Reference_database=Referensdatabas References=Referenser @@ -981,7 +981,7 @@ SQL_Database_Importer= SQL_Export= SQL_connection_established.=Ansluten_till_SQL-databas. Save=Spara -Save_actions= +Save_actions=Händelser_vid_sparning Save_all=Spara_alla Save_all_finished.=Alla_har_sparats. Save_all_open_databases=Spara_alla_öppna_databaser @@ -1026,7 +1026,7 @@ Select_Classpath_of_New_Importer= Select_Writer_document=Välj_Writer-dokument Select_a_Zip-archive=Välj_ett_Zip-arkiv Select_a_directory_where_the_search_shall_start.=Välj_en_mapp_där_sökningen_ska_börja. -Select_action= +Select_action=Välj_händelse Select_all=Välj_alla Select_at_least_one_entry_to_manage_keywords.=Välj_åtminstone_en_post_för_att_hantera_nyckelord. Select_directory=Välj_mapp @@ -1086,8 +1086,8 @@ Show_gridlines=Visa_rutnät Show_icons_for_groups=Visa_ikoner_för_grupper Show_last_names_only=Visa_bara_efternamn Show_names_unchanged=Visa_namnen_som_de_är -Show_number_of_elements_contained_in_each_group= -Show_only_preferences_deviating_from_their_default_value= +Show_number_of_elements_contained_in_each_group=Visa_antal_poster_i_varje_grupp +Show_only_preferences_deviating_from_their_default_value=Visa_bara_inställningar_som_skiljer_från_sitt_standardvärde Show_optional_fields=Visa_valfria_fält Show_preferences=Visa_inställningar Show_printed_status=Visa_utskriftsstatus @@ -1111,7 +1111,7 @@ Sort_automatically=Sortera_automatiskt Sort_the_following_fields_as_numeric_fields=Sortera_följande_fält_som_tal Sorted_all_subgroups_recursively.=Sorterade_alla_undergrupper_rekursivt. Sorted_immediate_subgroups.= -Special_Name_Formatters= +Special_Name_Formatters=Speciella_format_för_namn Special_table_columns=Speciella_kolumner Starting_import=Börjar_importera Starts_the_import_of_BibTeX_entries.=Börjar_importen_av_BibTeX-poster. @@ -1125,7 +1125,7 @@ String_dialog,_remove_string=Strängdialog,_ta_bort_sträng Strings=Strängar Strings_for_database=Strängar_för_databasen Style_selection=Stilval -Subdatabase_from_aux= +Subdatabase_from_aux=Databas_baserad_på_AUX-fil Subject_for_sending_an_email_with_references=Ämne_för_epost_med_referenser Switch_preview_layout=Byt_postvisningsstil Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.= @@ -1135,17 +1135,17 @@ Synchronize_files=Synkronisera_filer Synchronize_with_keywords=Synkronisera_med_nyckelord Synchronized_special_fields_based_on_keywords=Synkronisera_specialfält_med_hjälp_av_nyckelord Synchronizing_file_links...=Synkroniserar_fillänkar... -Table_and_entry_editor_colors= +Table_and_entry_editor_colors=Färger_för_tabell_och_posteditor Table_appearance=Tabellutseende Table_background_color=Bakgrundsfärg_för_tabellen -Table_font_size_is_%0= +Table_font_size_is_%0=Typsnittstorlek_för_tabellen_är_%0 Table_grid_color=Rutnätsfärg_för_tabellen -Table_row_height_padding= +Table_row_height_padding=Extra_höjd_på_tabellrader Table_text_color=Textfärg_för_tabellen Tabname=Fliknamn Target_file_cannot_be_a_directory.=Målfilen_kan_inte_vara_en_mapp. Tertiary_sort_criterion=Tredje_sorteringskriteriet -Test= +Test=Testa The_ACM_Digital_Library=ACMs_digitala_bibliotek The_Guide_to_Computing_Literature= The_PDF_contains_one_or_several_BibTeX-records.=PDFen_innehåller_en_eller_flera_BibTeX-poster. @@ -1260,12 +1260,12 @@ Use_IEEE_LaTeX_abbreviations=Använd_IEEE_LaTeX-förkortningar Use_regular_expression_search=Använd_sökning_med_reguljära_uttryck Use_abbreviated_and_full_firstname=Använd_förkortade_och_hela_förnamn Use_abbreviated_firstname_whenever_possible=Använd_om_möjligt_förkortade_förnamn -Use_autocompletion_for_the_following_fields= +Use_autocompletion_for_the_following_fields=Använd_automatisk_komplettering_för_följande_fält Use_custom_proxy_configuration=Använd_egen_proxykonfiguration Use_full_firstname_whenever_possible=Använd_hela_förnamnet_om_möjligt Use_other_look_and_feel=Använd_annan_'look-and-feel' -Use_the_bib_file_location_as_primary_file_directory= -Use_the_following_delimiter_character(s)\:= +Use_the_bib_file_location_as_primary_file_directory=Använd_bib-filens_plats_som_primär_filmapp +Use_the_following_delimiter_character(s)\:=Använd_följande_bokstäver_som_avgränsare\: Use_the_selected_directory_to_start_with_the_search.=Börja_sökningen_i_följande_mapp. User-specific_file_directory=Användarspecifik_filmapp Username=Användarnamn @@ -1278,19 +1278,19 @@ Waiting_for_save_operation_to_finish=Väntar_på_att_sparningen_ska_bli_färdig Warn_about_unresolved_duplicates_when_closing_inspection_window= Warn_before_overwriting_existing_keys=Varna_innan_befintliga_nycklar_skrivs_över Warning=Varning -Warning\:_%0_out_of_%1_entries_have_undefined_BibTeX_key.= +Warning\:_%0_out_of_%1_entries_have_undefined_BibTeX_key.=Varning\:_%0_av_%1_poster_har_odefinierade_BibTeX-nycklar. Warnings=Varningar Web_search=Websökning What_do_you_want_to_do?=Vad_vill_du_göra? What_would_you_like_to_clean_up?=Vad_vill_du_städa_upp? -When_adding/removing_keywords,_separate_them_by=När_nyckelord_läggs_tll/tas_bort,_separera_dem_med +When_adding/removing_keywords,_separate_them_by=När_nyckelord_läggs_till/tas_bort,_separera_dem_med When_downloading_files,_or_moving_linked_files_to_the_file_directory,_prefer_the_bib_file_location_rather_than_the_file_directory_set_above= When_opening_file_link,_search_for_matching_file_if_no_link_is_defined= Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.= Work_options= -Write_BibTeXEntry_as_XMP-metadata_to_PDF.= +Write_BibTeXEntry_as_XMP-metadata_to_PDF.=Skriv_BibTeX-posten_som_XMP-metadata_i_PDF. Write_XMP-metadata=Skriv_XMP-metadata -Write_XMP-metadata_for_all_PDFs_in_current_database?= +Write_XMP-metadata_for_all_PDFs_in_current_database?=Skriv_XMP-metadata_för_alla_PDFer_i_aktuell_databas? Write_XMP=Skriv_XMP Write_values_of_special_fields_as_separate_fields_to_BibTeX= Writing_XMP-metadata...=Skriver_XMP-metadata... @@ -1501,7 +1501,7 @@ PhD_thesis=Doktorsavhandling Redactor= Research_report=Forskningsrapport Reviser= -Section= +Section=Del Software=Mjukvara Technical_report=Teknisk_rapport U.S._patent= @@ -1562,4 +1562,4 @@ Please_open_%0_manually.=Öppna_%0_för_hand. The_link_has_been_copied_to_the_clipboard.=Länken_har_kopierats_till_urklipp. -Online_help_forum= +Online_help_forum=Onlineforum diff --git a/src/main/resources/l10n/Menu_sv.properties b/src/main/resources/l10n/Menu_sv.properties index e0d6c62cc6ab..09534a0a3983 100644 --- a/src/main/resources/l10n/Menu_sv.properties +++ b/src/main/resources/l10n/Menu_sv.properties @@ -99,4 +99,4 @@ Delete_entry=Radera_post Check_integrity=Testa_&integriteten Quality=&Kvalitet -Online_help_forum= +Online_help_forum=Onlineforum From a09cb53d478e8afe102bbe6debb6ad452b73f1b6 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Fri, 8 Jul 2016 13:46:56 +0200 Subject: [PATCH 187/268] Make sure the preferences are loaded in SearchGroupTest --- .../java/net/sf/jabref/logic/groups/SearchGroupTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java index 64c224dc5687..d9e1ae6ac6f0 100644 --- a/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java @@ -1,7 +1,10 @@ package net.sf.jabref.logic.groups; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -10,6 +13,11 @@ public class SearchGroupTest { + @BeforeClass + public static void setUp() { + Globals.prefs = JabRefPreferences.getInstance(); + } + @Test public void testContains() { SearchGroup group = new SearchGroup("myExplicitGroup", "review", From 212bebf477c5ec064e8d4cd6dd6b52df266a1610 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Fri, 8 Jul 2016 13:47:18 +0200 Subject: [PATCH 188/268] Move IdComparator to comparator package --- src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java | 2 +- .../sf/jabref/logic/{id => bibtex/comparator}/IdComparator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/net/sf/jabref/logic/{id => bibtex/comparator}/IdComparator.java (96%) diff --git a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java index 06f93c7d2885..244da0b7f7c1 100644 --- a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java @@ -41,8 +41,8 @@ import net.sf.jabref.logic.bibtex.comparator.CrossRefEntryComparator; import net.sf.jabref.logic.bibtex.comparator.FieldComparator; import net.sf.jabref.logic.bibtex.comparator.FieldComparatorStack; +import net.sf.jabref.logic.bibtex.comparator.IdComparator; import net.sf.jabref.logic.config.SaveOrderConfig; -import net.sf.jabref.logic.id.IdComparator; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.FieldChange; diff --git a/src/main/java/net/sf/jabref/logic/id/IdComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/IdComparator.java similarity index 96% rename from src/main/java/net/sf/jabref/logic/id/IdComparator.java rename to src/main/java/net/sf/jabref/logic/bibtex/comparator/IdComparator.java index c909b5d99e5f..e7db0d604999 100644 --- a/src/main/java/net/sf/jabref/logic/id/IdComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/IdComparator.java @@ -13,7 +13,7 @@ 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.id; +package net.sf.jabref.logic.bibtex.comparator; import java.util.Comparator; From fcebf46d3ee8772f23e3a31a0513cd76e7580b1a Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Fri, 8 Jul 2016 14:06:58 +0200 Subject: [PATCH 189/268] Move MimeTypeDetector to fulltext package --- .../net/sf/jabref/logic/fulltext/DoiResolution.java | 1 - .../net/sf/jabref/logic/fulltext/FindFullText.java | 1 - .../logic/{io => fulltext}/MimeTypeDetector.java | 2 +- .../{io => fulltext}/MimeTypeDetectorTest.java | 2 +- .../net/sf/jabref/logic/{io => fulltext}/empty.pdf | Bin 5 files changed, 2 insertions(+), 4 deletions(-) rename src/main/java/net/sf/jabref/logic/{io => fulltext}/MimeTypeDetector.java (95%) rename src/test/java/net/sf/jabref/logic/{io => fulltext}/MimeTypeDetectorTest.java (98%) rename src/test/resources/net/sf/jabref/logic/{io => fulltext}/empty.pdf (100%) diff --git a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java index f4e3098fe758..f2fc0b443b17 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java @@ -22,7 +22,6 @@ import java.util.Objects; import java.util.Optional; -import net.sf.jabref.logic.io.MimeTypeDetector; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java index 10bbe9be315a..118655061bad 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java @@ -7,7 +7,6 @@ import java.util.Optional; import net.sf.jabref.importer.fetcher.CrossRef; -import net.sf.jabref.logic.io.MimeTypeDetector; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/logic/io/MimeTypeDetector.java b/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java similarity index 95% rename from src/main/java/net/sf/jabref/logic/io/MimeTypeDetector.java rename to src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java index f8226a6cac92..7e7b444af429 100644 --- a/src/main/java/net/sf/jabref/logic/io/MimeTypeDetector.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java @@ -1,4 +1,4 @@ -package net.sf.jabref.logic.io; +package net.sf.jabref.logic.fulltext; import java.io.IOException; import java.net.URL; diff --git a/src/test/java/net/sf/jabref/logic/io/MimeTypeDetectorTest.java b/src/test/java/net/sf/jabref/logic/fulltext/MimeTypeDetectorTest.java similarity index 98% rename from src/test/java/net/sf/jabref/logic/io/MimeTypeDetectorTest.java rename to src/test/java/net/sf/jabref/logic/fulltext/MimeTypeDetectorTest.java index db342ede93eb..1f984dc3e85d 100644 --- a/src/test/java/net/sf/jabref/logic/io/MimeTypeDetectorTest.java +++ b/src/test/java/net/sf/jabref/logic/fulltext/MimeTypeDetectorTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.logic.io; +package net.sf.jabref.logic.fulltext; import java.net.URISyntaxException; diff --git a/src/test/resources/net/sf/jabref/logic/io/empty.pdf b/src/test/resources/net/sf/jabref/logic/fulltext/empty.pdf similarity index 100% rename from src/test/resources/net/sf/jabref/logic/io/empty.pdf rename to src/test/resources/net/sf/jabref/logic/fulltext/empty.pdf From 2cc669f5f449c4ad900e124ecbc97cf25e772dd5 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 9 Jul 2016 15:14:18 +0200 Subject: [PATCH 190/268] Corrected month value when using drop-down in entry editor (#1564) --- .../net/sf/jabref/gui/entryeditor/FieldExtraComponents.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index 9fe7087c9447..b4fd3baa8510 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -276,7 +276,7 @@ public static Optional getMonthExtraComponent(FieldEditor fieldEdito if (type == BibDatabaseMode.BIBLATEX) { fieldEditor.setText(String.valueOf(monthnumber)); } else { - fieldEditor.setText("#" + (MonthUtil.getMonthByNumber(monthnumber).bibtexFormat) + "#"); + fieldEditor.setText(MonthUtil.getMonthByNumber(monthnumber).bibtexFormat); } } else { fieldEditor.setText(""); From 06e62832fb652db0eeab31659634bc399cc30eda Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Mon, 11 Jul 2016 10:41:13 +0200 Subject: [PATCH 191/268] Move EmacsKeyBindings into keyboard package --- src/main/java/net/sf/jabref/gui/GUIGlobals.java | 2 +- .../sf/jabref/gui/keyboard}/EmacsKeyBindings.java | 2 +- .../java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java | 2 +- .../java/org/xnap/commons/gui/shortcut/package-info.java | 5 ----- 4 files changed, 3 insertions(+), 8 deletions(-) rename src/main/java/{org/xnap/commons/gui/shortcut => net/sf/jabref/gui/keyboard}/EmacsKeyBindings.java (99%) delete mode 100644 src/main/java/org/xnap/commons/gui/shortcut/package-info.java diff --git a/src/main/java/net/sf/jabref/gui/GUIGlobals.java b/src/main/java/net/sf/jabref/gui/GUIGlobals.java index 6b46f0f08383..92b02709f434 100644 --- a/src/main/java/net/sf/jabref/gui/GUIGlobals.java +++ b/src/main/java/net/sf/jabref/gui/GUIGlobals.java @@ -26,6 +26,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; +import net.sf.jabref.gui.keyboard.EmacsKeyBindings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; @@ -37,7 +38,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.xnap.commons.gui.shortcut.EmacsKeyBindings; /** * Static variables for graphics files and keyboard shortcuts. diff --git a/src/main/java/org/xnap/commons/gui/shortcut/EmacsKeyBindings.java b/src/main/java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java similarity index 99% rename from src/main/java/org/xnap/commons/gui/shortcut/EmacsKeyBindings.java rename to src/main/java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java index 55609ff2f7a4..8ff24a771c60 100644 --- a/src/main/java/org/xnap/commons/gui/shortcut/EmacsKeyBindings.java +++ b/src/main/java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java @@ -38,7 +38,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package org.xnap.commons.gui.shortcut; +package net.sf.jabref.gui.keyboard; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java index c3437ccf9871..51e3d897d5d5 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java @@ -31,6 +31,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.keyboard.EmacsKeyBindings; import net.sf.jabref.logic.autocompleter.AutoCompleteFirstNameMode; import net.sf.jabref.logic.autocompleter.AutoCompletePreferences; import net.sf.jabref.logic.l10n.Localization; @@ -38,7 +39,6 @@ import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; -import org.xnap.commons.gui.shortcut.EmacsKeyBindings; class EntryEditorPrefsTab extends JPanel implements PrefsTab { diff --git a/src/main/java/org/xnap/commons/gui/shortcut/package-info.java b/src/main/java/org/xnap/commons/gui/shortcut/package-info.java deleted file mode 100644 index faba338e1b8e..000000000000 --- a/src/main/java/org/xnap/commons/gui/shortcut/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * This package is a subset of the same package of XNap Commons (http://xnap-commons.sourceforge.net/) - * License: LGPL 2.1 - */ -package org.xnap.commons.gui.shortcut; \ No newline at end of file From 69b84f25fac28dac26ffb796ab773e94ce4eaa42 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Mon, 11 Jul 2016 11:50:47 +0200 Subject: [PATCH 192/268] Ignore unescaped hashes in the URL field --- .../java/net/sf/jabref/logic/integrity/IntegrityCheck.java | 7 ++++++- .../net/sf/jabref/logic/integrity/IntegrityCheckTest.java | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 10c6f5c4f5ad..1d45fddd36c2 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -400,7 +400,12 @@ private static class BibStringChecker implements Checker { @Override public List check(BibEntry entry) { List results = new ArrayList<>(); - for (Map.Entry field : entry.getFieldMap().entrySet()) { + + Map fields = entry.getFieldMap(); + // the url field should not be checked for hashes, as they are legal in this field + fields.remove("url"); + + for (Map.Entry field : fields.entrySet()) { Matcher hashMatcher = UNESCAPED_HASH.matcher(field.getValue()); int hashCount = 0; while (hashMatcher.find()) { diff --git a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java index f21cd2ce41cb..b2242e6d9b8b 100644 --- a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java @@ -41,6 +41,7 @@ public void setUp() { public void testUrlChecks() { assertCorrect(createContext("url", "http://www.google.com")); assertCorrect(createContext("url", "file://c:/asdf/asdf")); + assertCorrect(createContext("url", "http://scikit-learn.org/stable/modules/ensemble.html#random-forests")); assertWrong(createContext("url", "www.google.com")); assertWrong(createContext("url", "google.com")); From 8d7037b5b7ddb07b21e4d1ade8ca51445fc9d725 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Mon, 11 Jul 2016 11:53:15 +0200 Subject: [PATCH 193/268] Added changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0728942fe90a..73172e5e3f25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - The [online forum](http://discourse.jabref.org/) is now directly accessible via the "Help" menu ### Fixed +- Fixed [#1530](https://github.com/JabRef/jabref/issues/1530): Unescaped hashes in the url field are ignored by the integrity checker - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - Fixed [#1476](https://github.com/JabRef/jabref/issues/1476): NPE when importing from SQL DB because of missing DatabaseMode From b7ba0224caa421d948c9bc49100f89a28ff76693 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 12:14:46 +0200 Subject: [PATCH 194/268] Fixed number of entries fetched from Springer (#1562) * Fixed number of entries fetched from Springer --- CHANGELOG.md | 1 + .../net/sf/jabref/importer/fetcher/SpringerFetcher.java | 2 +- .../sf/jabref/importer/fileformat/JSONEntryParser.java | 9 +++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0728942fe90a..2390a87b21cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - The [online forum](http://discourse.jabref.org/) is now directly accessible via the "Help" menu ### Fixed +- Springer fetcher now fetches the requested number of entries (not one less as before) - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them - Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - Fixed [#1476](https://github.com/JabRef/jabref/issues/1476): NPE when importing from SQL DB because of missing DatabaseMode diff --git a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java index 6c3015387923..b74ebafc0506 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java @@ -93,7 +93,7 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint break; } - int noToFetch = Math.min(MAX_PER_PAGE, numberToFetch - startItem); + int noToFetch = Math.min(MAX_PER_PAGE, (numberToFetch - startItem) + 1); jsonResponse = Unirest .get(API_URL + encodedQuery + "&api_key=" + API_KEY + "&p=" + noToFetch + "&s=" + startItem) .header("accept", "application/json").asJson(); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java index b8c1afc2f1ae..8bba5ec0a588 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java @@ -233,10 +233,11 @@ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { } // Clean up abstract (often starting with Abstract) - String abstr = entry.getField("abstract"); - if ((abstr != null) && abstr.startsWith("Abstract")) { - entry.setField("abstract", abstr.substring(8)); - } + entry.getFieldOptional("abstract").ifPresent(abstractContents -> { + if (abstractContents.startsWith("Abstract")) { + entry.setField("abstract", abstractContents.substring(8)); + } + }); return entry; } From 0dfdebb0449c7948540616dee5f2298bf4344109 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 12:25:18 +0200 Subject: [PATCH 195/268] Some Codacy issues removed and some more use of getFieldOptional (#1561) --- .../sf/jabref/gui/maintable/MainTable.java | 17 +++++----- .../sf/jabref/gui/menus/RightClickMenu.java | 5 +-- .../jabref/gui/mergeentries/MergeEntries.java | 31 ++++++++++--------- .../jabref/logic/bibtex/BibEntryWriter.java | 12 +++---- .../sf/jabref/logic/openoffice/OOUtil.java | 9 +++--- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java index 0fbdf9754a8e..3aef6ffc7ddc 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java @@ -95,10 +95,6 @@ public class MainTable extends JTable { private final PersistenceTableColumnListener tableColumnListener; private final MainTableDataModel model; - public MainTableDataModel getTableModel() { - return model; - } - // Enum used to define how a cell should be rendered. private enum CellRendererMode { REQUIRED, @@ -188,6 +184,10 @@ public JScrollPane getPane() { return pane; } + public MainTableDataModel getTableModel() { + return model; + } + @Override public String getToolTipText(MouseEvent e) { @@ -216,10 +216,12 @@ public TableCellRenderer getCellRenderer(int row, int column) { CellRendererMode status = getCellStatus(row, column); - if (!(model.getSearchState() == MainTableDataModel.DisplayOption.FLOAT) || matches(row, model.getSearchState() != MainTableDataModel.DisplayOption.DISABLED ? SearchMatcher.INSTANCE : null)) { + if ((model.getSearchState() != MainTableDataModel.DisplayOption.FLOAT) || matches(row, + model.getSearchState() != MainTableDataModel.DisplayOption.DISABLED ? SearchMatcher.INSTANCE : null)) { score++; } - if (!(model.getGroupingState() == MainTableDataModel.DisplayOption.FLOAT) || matches(row, model.getGroupingState() != MainTableDataModel.DisplayOption.DISABLED ? GroupMatcher.INSTANCE : null)) { + if ((model.getGroupingState() != MainTableDataModel.DisplayOption.FLOAT) || matches(row, + model.getGroupingState() != MainTableDataModel.DisplayOption.DISABLED ? GroupMatcher.INSTANCE : null)) { score += 2; } @@ -549,7 +551,8 @@ public void updateFont() { public void ensureVisible(int row) { JScrollBar vert = pane.getVerticalScrollBar(); int y = row * getRowHeight(); - if ((y < vert.getValue()) || ((y > (vert.getValue() + vert.getVisibleAmount())) && !(model.getSearchState() == MainTableDataModel.DisplayOption.FLOAT))) { + if ((y < vert.getValue()) || ((y > (vert.getValue() + vert.getVisibleAmount())) + && (model.getSearchState() != MainTableDataModel.DisplayOption.FLOAT))) { scrollToCenter(row, 1); } diff --git a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java index 25cd210f2630..8d1bbd7b2e5b 100644 --- a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java @@ -16,6 +16,7 @@ package net.sf.jabref.gui.menus; import java.awt.event.ActionEvent; +import java.util.Optional; import javax.swing.AbstractAction; import javax.swing.Icon; @@ -106,9 +107,9 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) { add(markSpecific); add(new GeneralAction(Actions.UNMARK_ENTRIES, Localization.lang("Unmark entries"), IconTheme.JabRefIcon.UNMARK_ENTRIES.getSmallIcon())); } else if (be != null) { - String marked = be.getField(InternalBibtexFields.MARKED); + Optional marked = be.getFieldOptional(InternalBibtexFields.MARKED); // We have to check for "" too as the marked field may be empty - if ((marked == null) || marked.isEmpty()) { + if ((!marked.isPresent()) || marked.get().isEmpty()) { add(new GeneralAction(Actions.MARK_ENTRIES, Localization.lang("Mark entry"), IconTheme.JabRefIcon.MARK_ENTRIES.getSmallIcon())); add(markSpecific); } else { diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java index 0cea3f813a9d..08a2a5e0f12b 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -236,9 +237,9 @@ private void initialize() { for (String field : allFields) { JLabel label = boldFontLabel(new SentenceCaseFormatter().format(field)); mergePanel.add(label, cc.xy(1, (2 * row) - 1, "left, top")); - String leftString = leftEntry.getField(field); - String rightString = rightEntry.getField(field); - if (Objects.equals(leftString, rightString)) { + Optional leftString = leftEntry.getFieldOptional(field); + Optional rightString = rightEntry.getFieldOptional(field); + if (leftString.equals(rightString)) { identicalFields.add(field); } else { differentFields.add(field); @@ -247,7 +248,7 @@ private void initialize() { maxLabelWidth = Math.max(maxLabelWidth, label.getPreferredSize().width); // Left text pane - if (leftString != null) { + if (leftString.isPresent()) { JTextPane tf = getStyledTextPane(); mergePanel.add(tf, cc.xy(3, (2 * row) - 1, "f, f")); leftTextPanes.put(field, tf); @@ -255,7 +256,7 @@ private void initialize() { // Add radio buttons if the two entries do not have identical fields if (identicalFields.contains(field)) { - mergedEntry.setField(field, leftString); + mergedEntry.setField(field, leftString.get()); // Will only happen if both entries have the field and the content is identical } else { ButtonGroup group = new ButtonGroup(); List list = new ArrayList<>(3); @@ -267,19 +268,19 @@ private void initialize() { list.add(button); } radioButtons.put(field, list); - if (leftString == null) { - list.get(0).setEnabled(false); - list.get(2).setSelected(true); - } else { + if (leftString.isPresent()) { list.get(0).setSelected(true); - if (rightString == null) { + if (!rightString.isPresent()) { list.get(2).setEnabled(false); } + } else { + list.get(0).setEnabled(false); + list.get(2).setSelected(true); } } // Right text pane - if (rightString != null) { + if (rightString.isPresent()) { JTextPane tf = getStyledTextPane(); mergePanel.add(tf, cc.xy(11, (2 * row) - 1, "f, f")); rightTextPanes.put(field, tf); @@ -364,8 +365,8 @@ private void setupFields() { private void updateTextPanes(Collection fields) { int oldScrollPaneValue = scrollPane.getVerticalScrollBar().getValue(); for (String field : fields) { - String leftString = leftEntry.getField(field); - String rightString = rightEntry.getField(field); + String leftString = leftEntry.getFieldOptional(field).orElse(""); + String rightString = rightEntry.getFieldOptional(field).orElse(""); switch (diffMode.getSelectedIndex()) { case 0: // Plain text break; @@ -521,9 +522,9 @@ private void updateAll() { // Check the potentially different fields for (String field : differentFields) { if (radioButtons.get(field).get(0).isSelected()) { - mergedEntry.setField(field, leftEntry.getField(field)); + mergedEntry.setField(field, leftEntry.getFieldOptional(field).get()); // Will only happen if field exists } else if (radioButtons.get(field).get(2).isSelected()) { - mergedEntry.setField(field, rightEntry.getField(field)); + mergedEntry.setField(field, rightEntry.getFieldOptional(field).get()); // Will only happen if field exists } else { mergedEntry.clearField(field); } diff --git a/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java index 629c8c1d32b2..8cba85933a48 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java @@ -18,8 +18,6 @@ import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.InternalBibtexFields; -import com.google.common.base.Strings; - public class BibEntryWriter { @@ -135,14 +133,14 @@ private void writeKeyField(BibEntry entry, Writer out) throws IOException { * @throws IOException In case of an IO error */ private void writeField(BibEntry entry, Writer out, String name, int indentation) throws IOException { - String field = entry.getField(name); - // only write field if is is not empty or if empty fields should be included - // the first condition mirrors mirror behavior of com.jgoodies.common.base.Strings.isNotBlank(str) - if (!Strings.nullToEmpty(field).trim().isEmpty()) { + Optional field = entry.getFieldOptional(name); + // only write field if is is not empty + // field.ifPresent does not work as an IOException may be thrown + if (field.isPresent() && !field.get().trim().isEmpty()) { out.write(" " + getFieldDisplayName(name, indentation)); try { - out.write(fieldFormatter.format(field, name)); + out.write(fieldFormatter.format(field.get(), name)); out.write(',' + Globals.NEWLINE); } catch (IOException ex) { throw new IOException("Error in field '" + name + "': " + ex.getMessage()); diff --git a/src/main/java/net/sf/jabref/logic/openoffice/OOUtil.java b/src/main/java/net/sf/jabref/logic/openoffice/OOUtil.java index d0ea1729ec03..bd1cf7b07355 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/OOUtil.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/OOUtil.java @@ -16,6 +16,7 @@ package net.sf.jabref.logic.openoffice; import java.util.EnumSet; +import java.util.Optional; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,7 +88,7 @@ public static void insertFullReferenceAtCurrentLocation(XText text, XTextCursor WrappedTargetException, IllegalArgumentException { // Backup the value of the uniq field, just in case the entry already has it: - String oldUniqVal = entry.getField(UNIQUEFIER_FIELD); + Optional oldUniqVal = entry.getFieldOptional(UNIQUEFIER_FIELD); // Set the uniq field with the supplied uniquefier: @@ -101,10 +102,10 @@ public static void insertFullReferenceAtCurrentLocation(XText text, XTextCursor String lText = layout.doLayout(entry, database); // Afterwards, reset the old value: - if (oldUniqVal == null) { - entry.clearField(UNIQUEFIER_FIELD); + if (oldUniqVal.isPresent()) { + entry.setField(UNIQUEFIER_FIELD, oldUniqVal.get()); } else { - entry.setField(UNIQUEFIER_FIELD, oldUniqVal); + entry.clearField(UNIQUEFIER_FIELD); } // Insert the formatted text: From 982e56599838c0f23384089e3311b57df4dfa139 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 12:26:54 +0200 Subject: [PATCH 196/268] Fixed #1534 (#1559) --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/EntryMarker.java | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2390a87b21cd..bd03f71147d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1444](https://github.com/JabRef/jabref/issues/1444): Implement getExtension and getDescription for importers. - Fixed [#1507](https://github.com/JabRef/jabref/issues/1507): Keywords are now separated by the delimiter specified in the preferences - Fixed [#1484](https://github.com/JabRef/jabref/issues/1484): HTML export handles some UTF characters wrong +- Fixed [#1534](https://github.com/JabRef/jabref/issues/1534): "Mark entries imported into database" does not work correctly ### Removed diff --git a/src/main/java/net/sf/jabref/gui/EntryMarker.java b/src/main/java/net/sf/jabref/gui/EntryMarker.java index 8435cd174f50..60ba56bbb77c 100644 --- a/src/main/java/net/sf/jabref/gui/EntryMarker.java +++ b/src/main/java/net/sf/jabref/gui/EntryMarker.java @@ -196,8 +196,6 @@ public static int isMarked(BibEntry be) { } public static boolean shouldMarkEntries() { - return (Globals.prefs.getBoolean(JabRefPreferences.MARK_IMPORTED_ENTRIES) - && (Globals.prefs.getBoolean(JabRefPreferences.USE_OWNER) - || Globals.prefs.getBoolean(JabRefPreferences.USE_TIME_STAMP))); + return Globals.prefs.getBoolean(JabRefPreferences.MARK_IMPORTED_ENTRIES); } } From 6d10f1833f35d7fe8ca880f64c667afb888a78c7 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 12:27:39 +0200 Subject: [PATCH 197/268] Moved final methods from Util (#1560) * Moved final methods from Util * Fixed formatting * Removed JavaDoc --- .../jabref/gui/groups/AddToGroupAction.java | 5 +- .../net/sf/jabref/gui/groups/GroupDialog.java | 3 +- .../net/sf/jabref/gui/groups/GroupsTree.java | 3 +- .../gui/groups/RemoveFromGroupAction.java | 3 +- .../groups/WarnAssignmentSideEffects.java} | 69 +++---------------- .../jabref/sql/importer/DbImportAction.java | 25 ++++++- 6 files changed, 36 insertions(+), 72 deletions(-) rename src/main/java/net/sf/jabref/{util/Util.java => gui/groups/WarnAssignmentSideEffects.java} (64%) diff --git a/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java b/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java index 779d9eb62572..6e3403a5e7d9 100644 --- a/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java +++ b/src/main/java/net/sf/jabref/gui/groups/AddToGroupAction.java @@ -29,7 +29,6 @@ import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.util.Util; public class AddToGroupAction extends AbstractAction { @@ -93,7 +92,7 @@ public void moveToGroup(List entries, NamedCompound undoAll) { List affectedGroups = groupsContainingEntries.stream().map(GroupTreeNode::getGroup).collect( Collectors.toList()); affectedGroups.add(node.getNode().getGroup()); - if (!Util.warnAssignmentSideEffects(affectedGroups, panel.frame())) { + if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(affectedGroups, panel.frame())) { return; // user aborted operation } @@ -113,7 +112,7 @@ public void moveToGroup(List entries, NamedCompound undoAll) { } public void addToGroup(List entries, NamedCompound undo) { - if (!Util.warnAssignmentSideEffects(node.getNode().getGroup(), panel.frame())) { + if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(node.getNode().getGroup(), panel.frame())) { return; // user aborted operation } diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index 9ce4a6e21d4c..ff788415f47c 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -65,7 +65,6 @@ import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.util.Util; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.DefaultFormBuilder; @@ -483,7 +482,7 @@ private void addPreviousEntries() { } } if (!list.isEmpty()) { - if (!Util.warnAssignmentSideEffects(mResultingGroup, this)) { + if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(mResultingGroup, this)) { return; } // the undo information for a conversion to an ExplicitGroup is diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java index b4176a41ab68..052389bd2443 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java @@ -56,7 +56,6 @@ import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.groups.MoveGroupChange; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.util.Util; public class GroupsTree extends JTree implements DragSourceListener, DropTargetListener, DragGestureListener { @@ -302,7 +301,7 @@ public void drop(DropTargetDropEvent dtde) { // warn if assignment has undesired side effects (modifies a // field != keywords) - if (!Util.warnAssignmentSideEffects(group, groupSelector.frame)) + if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(group, groupSelector.frame)) { return; // user aborted operation } diff --git a/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java b/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java index fe17c586925d..7c06409d7c0b 100644 --- a/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java +++ b/src/main/java/net/sf/jabref/gui/groups/RemoveFromGroupAction.java @@ -23,7 +23,6 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.util.Util; public class RemoveFromGroupAction extends AbstractAction { @@ -52,7 +51,7 @@ public void setBasePanel(BasePanel panel) { @Override public void actionPerformed(ActionEvent evt) { // warn if assignment has undesired side effects (modifies a field != keywords) - if (!Util.warnAssignmentSideEffects(mNode.getNode().getGroup(), mPanel.frame())) { + if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(mNode.getNode().getGroup(), mPanel.frame())) { return; // user aborted operation } diff --git a/src/main/java/net/sf/jabref/util/Util.java b/src/main/java/net/sf/jabref/gui/groups/WarnAssignmentSideEffects.java similarity index 64% rename from src/main/java/net/sf/jabref/util/Util.java rename to src/main/java/net/sf/jabref/gui/groups/WarnAssignmentSideEffects.java index c2562cdd64ac..524b83f3fdf1 100644 --- a/src/main/java/net/sf/jabref/util/Util.java +++ b/src/main/java/net/sf/jabref/gui/groups/WarnAssignmentSideEffects.java @@ -1,24 +1,4 @@ -/* Copyright (C) 2003-2016 JabRef contributors. - Copyright (C) 2015 Oliver Kopp - - 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. - */ - -// created by : Morten O. Alver 2003 - -package net.sf.jabref.util; +package net.sf.jabref.gui.groups; import java.awt.Component; import java.util.ArrayList; @@ -27,49 +7,12 @@ import javax.swing.JOptionPane; -import net.sf.jabref.gui.worker.AbstractWorker; -import net.sf.jabref.gui.worker.CallBack; -import net.sf.jabref.gui.worker.Worker; import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.KeywordGroup; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.InternalBibtexFields; -/** - * utility functions - */ -public class Util { - - /** - * Run an AbstractWorker's methods using Spin features to put each method on the correct thread. - * - * @param worker The worker to run. - * @throws Throwable - */ - public static void runAbstractWorker(AbstractWorker worker) throws Throwable { - // This part uses Spin's features: - Worker wrk = worker.getWorker(); - // The Worker returned by getWorker() has been wrapped - // by Spin.off(), which makes its methods be run in - // a different thread from the EDT. - CallBack clb = worker.getCallBack(); - - worker.init(); // This method runs in this same thread, the EDT. - // Useful for initial GUI actions, like printing a message. - - // The CallBack returned by getCallBack() has been wrapped - // by Spin.over(), which makes its methods be run on - // the EDT. - wrk.run(); // Runs the potentially time-consuming action - // without freezing the GUI. The magic is that THIS line - // of execution will not continue until run() is finished. - clb.update(); // Runs the update() method on the EDT. - } - - - public static boolean warnAssignmentSideEffects(AbstractGroup group, Component parent) { - return warnAssignmentSideEffects(Collections.singletonList(group), parent); - } +public class WarnAssignmentSideEffects { /** * Warns the user of undesired side effects of an explicit assignment/removal of entries to/from this group. @@ -85,8 +28,8 @@ public static boolean warnAssignmentSideEffects(List groups, Comp List affectedFields = new ArrayList<>(); for (AbstractGroup group : groups) { if (group instanceof KeywordGroup) { - KeywordGroup kg = (KeywordGroup) group; - String field = kg.getSearchField().toLowerCase(); + KeywordGroup keywordGroup = (KeywordGroup) group; + String field = keywordGroup.getSearchField().toLowerCase(); if ("keywords".equals(field) || "groups".equals(field)) { continue; // this is not undesired } @@ -144,4 +87,8 @@ public static boolean warnAssignmentSideEffects(List groups, Comp // return true; // found no side effects } + public static boolean warnAssignmentSideEffects(AbstractGroup group, Component parent) { + return warnAssignmentSideEffects(Collections.singletonList(group), parent); + } + } diff --git a/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java b/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java index 9b2ea62b9757..cbef631868ca 100644 --- a/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java +++ b/src/main/java/net/sf/jabref/sql/importer/DbImportAction.java @@ -32,6 +32,8 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.gui.worker.CallBack; +import net.sf.jabref.gui.worker.Worker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.sql.DBConnectDialog; import net.sf.jabref.sql.DBExporterAndImporterFactory; @@ -39,7 +41,6 @@ import net.sf.jabref.sql.DBStrings; import net.sf.jabref.sql.DatabaseUtil; import net.sf.jabref.sql.SQLUtil; -import net.sf.jabref.util.Util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -77,7 +78,7 @@ public DbImpAction() { @Override public void actionPerformed(ActionEvent e) { try { - Util.runAbstractWorker(DbImportAction.this); + runInSeparateThread(); } catch (Throwable throwable) { LOGGER.warn("Problem importing from database", throwable); } @@ -196,4 +197,24 @@ public void update() { frame.output(Localization.lang("Imported %0 databases successfully", Integer.toString(databases.size()))); } + private void runInSeparateThread() throws Throwable { + // This part uses Spin's features: + Worker wrk = this.getWorker(); + // The Worker returned by getWorker() has been wrapped + // by Spin.off(), which makes its methods be run in + // a different thread from the EDT. + CallBack clb = this.getCallBack(); + + this.init(); // This method runs in this same thread, the EDT. + // Useful for initial GUI actions, like printing a message. + + // The CallBack returned by getCallBack() has been wrapped + // by Spin.over(), which makes its methods be run on + // the EDT. + wrk.run(); // Runs the potentially time-consuming action + // without freezing the GUI. The magic is that THIS line + // of execution will not continue until run() is finished. + clb.update(); // Runs the update() method on the EDT. + } + } From acf67007e40a4abefc1e53679f8f75efcd1da880 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 13:52:06 +0200 Subject: [PATCH 198/268] Some internationalization improvements (#1557) --- src/main/java/net/sf/jabref/JabRefGUI.java | 6 ++--- .../sf/jabref/external/WriteXMPAction.java | 3 ++- .../java/net/sf/jabref/gui/BasePanel.java | 2 +- .../sf/jabref/gui/ContentSelectorDialog2.java | 6 ++--- .../net/sf/jabref/gui/EntryTypeDialog.java | 2 +- .../jabref/gui/FindUnlinkedFilesDialog.java | 4 ++-- .../java/net/sf/jabref/gui/StringDialog.java | 2 +- .../gui/preftabs/AppearancePrefsTab.java | 2 +- .../gui/preftabs/ImportSettingsTab.java | 2 +- .../importer/ImportCustomizationDialog.java | 2 +- .../net/sf/jabref/pdfimport/ImportDialog.java | 18 +++++++-------- src/main/resources/l10n/JabRef_da.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_de.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_en.properties | 22 +++++++++---------- src/main/resources/l10n/JabRef_es.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_fa.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_fr.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_in.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_it.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_ja.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_nl.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_no.properties | 20 ++++++++--------- .../resources/l10n/JabRef_pt_BR.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_ru.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_sv.properties | 19 ++++++++-------- src/main/resources/l10n/JabRef_tr.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_vi.properties | 20 ++++++++--------- src/main/resources/l10n/JabRef_zh.properties | 20 ++++++++--------- 28 files changed, 194 insertions(+), 196 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefGUI.java b/src/main/java/net/sf/jabref/JabRefGUI.java index d6c7759e2733..b63bafc3e95a 100644 --- a/src/main/java/net/sf/jabref/JabRefGUI.java +++ b/src/main/java/net/sf/jabref/JabRefGUI.java @@ -97,7 +97,7 @@ private void openWindow() { // "lcd" instead of "on" because of http://wiki.netbeans.org/FaqFontRendering and http://docs.oracle.com/javase/6/docs/technotes/guides/2d/flags.html#aaFonts System.setProperty("awt.useSystemAAFontSettings", "lcd"); - // Look & Feel. This MUST be the first thing to do before loading any Swing-specific code! + // look and feel. This MUST be the first thing to do before loading any Swing-specific code! setLookAndFeel(); // If the option is enabled, open the last edited databases, if any. @@ -274,9 +274,9 @@ private void setLookAndFeel() { // notify the user JOptionPane.showMessageDialog(JabRefGUI.getMainFrame(), Localization - .lang("Unable to find the requested Look & Feel and thus the default one is used."), + .lang("Unable to find the requested look and feel and thus the default one is used."), Localization.lang("Warning"), JOptionPane.WARNING_MESSAGE); - LOGGER.warn("Unable to find requested Look and Feel", e); + LOGGER.warn("Unable to find requested look and feel", e); } } } catch (Exception e) { diff --git a/src/main/java/net/sf/jabref/external/WriteXMPAction.java b/src/main/java/net/sf/jabref/external/WriteXMPAction.java index d6ae9564cca9..e031a12541ff 100644 --- a/src/main/java/net/sf/jabref/external/WriteXMPAction.java +++ b/src/main/java/net/sf/jabref/external/WriteXMPAction.java @@ -91,7 +91,8 @@ public void init() { if (entries.isEmpty()) { - JOptionPane.showMessageDialog(panel, Localization.lang("This operation requires at least one entry."), + JOptionPane.showMessageDialog(panel, + Localization.lang("This operation requires one or more entries to be selected."), Localization.lang("Write XMP-metadata"), JOptionPane.ERROR_MESSAGE); goOn = false; return; diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 61d36f485dd1..44346461cc38 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -1958,7 +1958,7 @@ public boolean showDeleteConfirmationDialog(int numberOfEntries) { msg = Localization.lang("Really delete the selected entry?"); String title = Localization.lang("Delete entry"); if (numberOfEntries > 1) { - msg = Localization.lang("Really delete the selected %0 entries?", Integer.toString(numberOfEntries)); + msg = Localization.lang("Really delete the %0 selected entries?", Integer.toString(numberOfEntries)); title = Localization.lang("Delete multiple entries"); } diff --git a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java index d2a7b81ee115..e5274029ab6e 100644 --- a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java +++ b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java @@ -100,7 +100,7 @@ class ContentSelectorDialog2 extends JDialog { */ public ContentSelectorDialog2(Window owner, JabRefFrame frame, BasePanel panel, boolean modal, String fieldName) { - super(owner, Localization.lang("Setup selectors")); + super(owner, Localization.lang("Manage content selectors")); this.setModal(modal); this.metaData = panel.getBibDatabaseContext().getMetaData(); this.frame = frame; @@ -190,7 +190,7 @@ private void setupActions() { applyChanges(); dispose(); } catch (Exception ex) { - LOGGER.info("Could not apply changes in \"Setup selectors\"", ex); + LOGGER.info("Could not apply changes in \"Manage content selectors\"", ex); JOptionPane.showMessageDialog(frame, Localization.lang("Could not apply changes.")); } }); @@ -203,7 +203,7 @@ private void setupActions() { try { applyChanges(); } catch (Exception ex) { - LOGGER.info("Could not apply changes in \"Setup selectors\"", ex); + LOGGER.info("Could not apply changes in \"Manage content selectors\"", ex); JOptionPane.showMessageDialog(frame, Localization.lang("Could not apply changes.")); } }); diff --git a/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java b/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java index 8861e72c4ac6..173db132dc1a 100644 --- a/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java +++ b/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java @@ -111,7 +111,7 @@ private JPanel createEntryGroupsPanel() { } else { panel.add(createEntryGroupPanel("BibTeX", BibtexEntryTypes.ALL)); panel.add(createEntryGroupPanel("IEEETran", IEEETranEntryTypes.ALL)); - panel.add(createEntryGroupPanel("Custom", CustomEntryTypesManager.ALL)); + panel.add(createEntryGroupPanel(Localization.lang("Custom"), CustomEntryTypesManager.ALL)); } return panel; diff --git a/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java b/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java index e3fe64581c11..c8b3d4f06096 100644 --- a/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java +++ b/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java @@ -388,7 +388,7 @@ private Path chooseDirectory() { fileChooser = new JFileChooser(); fileChooser.setAutoscrolls(true); fileChooser.setDialogTitle(Localization.lang("Select directory")); - fileChooser.setApproveButtonText(Localization.lang("Choose Directory")); + fileChooser.setApproveButtonText(Localization.lang("Choose directory")); fileChooser.setApproveButtonToolTipText( Localization.lang("Use the selected directory to start with the search.")); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -654,7 +654,7 @@ private void searchFinishedHandler(CheckableTreeNode rootNode) { private void setupActions() { /** - * Stores the selected Directory. + * Stores the selected directory. */ buttonBrowse.addActionListener(e -> { Path selectedDirectory = chooseDirectory(); diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index 51f4b3647275..57d642e5eeef 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -429,7 +429,7 @@ public void actionPerformed(ActionEvent e) { // keystroke. This makes the content hang on the screen. assureNotEditing(); - String msg = (sel.length > 1 ? Localization.lang("Really delete the selected %0 entries?", + String msg = (sel.length > 1 ? Localization.lang("Really delete the %0 selected entries?", Integer.toString(sel.length)) : Localization.lang("Really delete the selected entry?")); int answer = JOptionPane.showConfirmDialog(parent, msg, Localization.lang("Delete strings"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java index 3ba4fa5dc4ae..26248ffc87db 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java @@ -56,7 +56,7 @@ class AppearancePrefsTab extends JPanel implements PrefsTab { private boolean oldOverrideFontSize; private final JTextField fontSize; private final JTextField rowPadding; - // Look & Feel + // look and feel private final JComboBox classNamesLAF; private String currentLAF = ""; private boolean useDefaultLAF; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java index dc69e40ecd0a..29e15a175229 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java @@ -84,7 +84,7 @@ public ImportSettingsTab(JabRefPreferences prefs) { DefaultFormBuilder builder = new DefaultFormBuilder(layout); JPanel pan = new JPanel(); - builder.appendSeparator(Localization.lang("Default import style for drag&drop of PDFs")); + builder.appendSeparator(Localization.lang("Default import style for drag and drop of PDFs")); builder.nextLine(); builder.append(pan); builder.append(radioButtonNoMeta); diff --git a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java index 579c7e662ffc..02430db7513a 100644 --- a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java @@ -105,7 +105,7 @@ public ImportCustomizationDialog(final JabRefFrame frame) { String chosenFileStr = null; if (importer.getBasePath() != null) { chosenFileStr = FileDialogs.getNewFile(frame, importer.getFileFromBasePath(), - Collections.singletonList(".class"), Localization.lang("Select new ImportFormat Subclass"), + Collections.singletonList(".class"), Localization.lang("Select new ImportFormat subclass"), JFileChooser.CUSTOM_DIALOG, false); } if (chosenFileStr != null) { diff --git a/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java b/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java index a2b978aa19ee..ec620d283eb7 100644 --- a/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java +++ b/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java @@ -69,9 +69,9 @@ public ImportDialog(boolean targetIsARow, String fileName) { setContentPane(contentPane); JPanel panel3 = new JPanel(); panel3.setBackground(new Color(-1643275)); - JLabel labelHeadline = new JLabel(Localization.lang("Import_metadata_from:")); + JLabel labelHeadline = new JLabel(Localization.lang("Import metadata from:")); labelHeadline.setFont(new Font(labelHeadline.getFont().getName(), Font.BOLD, 14)); - JLabel labelSubHeadline = new JLabel(Localization.lang("Choose_the_source_for_the_metadata_import")); + JLabel labelSubHeadline = new JLabel(Localization.lang("Choose the source for the metadata import")); labelSubHeadline.setFont(new Font(labelSubHeadline.getFont().getName(), labelSubHeadline.getFont().getStyle(), 13)); JLabel labelFileName = new JLabel(); labelFileName.setFont(new Font(labelHeadline.getFont().getName(), Font.BOLD, 14)); @@ -86,20 +86,20 @@ public ImportDialog(boolean targetIsARow, String fileName) { panel3.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); panel3.add(headLinePanel); panel3.add(labelSubHeadline); - radioButtonNoMeta = new JRadioButton(Localization.lang("Create_blank_entry_linking_the_PDF")); - radioButtonXmp = new JRadioButton(Localization.lang("Create_entry_based_on_XMP_data")); - radioButtonPDFcontent = new JRadioButton(Localization.lang("Create_entry_based_on_content")); - radioButtononlyAttachPDF = new JRadioButton(Localization.lang("Only_attach_PDF")); + radioButtonNoMeta = new JRadioButton(Localization.lang("Create blank entry linking the PDF")); + radioButtonXmp = new JRadioButton(Localization.lang("Create entry based on XMP data")); + radioButtonPDFcontent = new JRadioButton(Localization.lang("Create entry based on content")); + radioButtononlyAttachPDF = new JRadioButton(Localization.lang("Only attach PDF")); JButton buttonOK = new JButton(Localization.lang("OK")); JButton buttonCancel = new JButton(Localization.lang("Cancel")); checkBoxDoNotShowAgain = new JCheckBox(Localization.lang("Do not show this box again for this import")); useDefaultPDFImportStyle = new JCheckBox(Localization.lang("Always use this PDF import style (and do not ask for each import)")); DefaultFormBuilder b = new DefaultFormBuilder(new FormLayout("left:pref, 5dlu, left:pref:grow", "")); - b.appendSeparator(Localization.lang("Create New Entry")); + b.appendSeparator(Localization.lang("Create new entry")); b.append(radioButtonNoMeta, 3); b.append(radioButtonXmp, 3); b.append(radioButtonPDFcontent, 3); - b.appendSeparator(Localization.lang("Update_Existing_Entry")); + b.appendSeparator(Localization.lang("Update existing entry")); b.append(radioButtononlyAttachPDF, 3); b.nextLine(); b.append(checkBoxDoNotShowAgain); @@ -121,7 +121,7 @@ public ImportDialog(boolean targetIsARow, String fileName) { } String name = new File(fileName).getName(); labelFileName.setText(StringUtil.limitStringLength(name, 34)); - this.setTitle(Localization.lang("Import_Metadata_From_PDF")); + this.setTitle(Localization.lang("Import metadata from PDF")); setModal(true); getRootPane().setDefaultButton(buttonOK); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index d30a8dd7d5bf..be1e215b013c 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -669,7 +669,7 @@ Select_encoding=Vælg_tegnkodning Select_entry_type=Vælg_posttype Select_external_application=Vælg_ekstern_applikation Select_file_from_ZIP-archive=Vælg_fil_fra_ZIP-fil -Select_new_ImportFormat_Subclass=Vælg_klasse_til_nyt_importformat +Select_new_ImportFormat_subclass=Vælg_klasse_til_nyt_importformat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Vælg_forgreningerne_for_at_inspicere_og_acceptere_eller_forkaste_ændringer Selected_entries=Valgte_poster Server_hostname=Server_værtsnavn @@ -681,7 +681,6 @@ Set_general_fields=Tilpas_generelle_felter Set_main_external_file_directory=Sæt_hovedbibliotek_for_eksterne_links Set_table_font=Vælg_tabelskrifttype Settings=Indstillinger -Setup_selectors=Opsæt_ordlister Shortcut=Genvej Show/edit_BibTeX_source=Vis/rediger_BibTeX-kilde Show_'Firstname_Lastname'=Vis_'Fornavn_Efternavn' @@ -767,7 +766,6 @@ This_group_contains_entries_whose_%0_field_contains_the_regular_expressio This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Dette_får_JabRef_til_at_slå_hvert_fil-link_op_og_tjekke,_om_filen_eksisterer._Hvis_ikke_vil_du_få_mulighed_for_at
    løse_problemet. #This_makes_JabRef_look_up_each_%0_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Dette_får_JabRef_til_at_undersøge_hvert_%0-link_og_tjekke,_om_filen_eksisterer._Hvis_ikke_vil_du_få_mulighed
    for_at_løse_problemet. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Denne_operation_kræver,_at_alle_valgte_poster_har_definerede_BibTeX-nøgler. -This_operation_requires_at_least_one_entry.=Denne_operation_kræver_mindst_en_post. This_operation_requires_one_or_more_entries_to_be_selected.=Denne_operation_kræver,_at_en_eller_flere_poster_er_valgt. Toggle_abbreviation=Forkort/ekspander Toggle_entry_preview=Vis/skjul_forhåndsvisning @@ -992,8 +990,8 @@ Create_blank_entry_linking_the_PDF=Opret_tom_post_med_link_til_PDF-filen Only_attach_PDF=Tilføj_kun_PDF Title=Titel No_internet_connection.=Ingen_Internetforbindelse. -Create_New_Entry=Opret_ny_post -Update_Existing_Entry=Opdater_eksisterende_post +Create_new_entry=Opret_ny_post +Update_existing_entry=Opdater_eksisterende_post Autocomplete_names_in_'Firstname_Lastname'_format_only=Autofuldfør_kun_navne_i_formatet_'Fornavn_Efternavn' Autocomplete_names_in_'Lastname,_Firstname'_format_only=Autofuldfør_kun_navne_i_formatet_'Efternavn,_Fornavn' Autocomplete_names_in_both_formats=Autofuldfør_navne_i_begge_formater @@ -1014,7 +1012,7 @@ exportFormat=Eksportformat Output_file_missing=Output-fil_mangler No_search_matches.=Ingen_søgeresultater. The_output_option_depends_on_a_valid_input_option.=Outputindstilling_kræver_en_gyldig_inputindstilling. -Default_import_style_for_drag&drop_of_PDFs=Standard_importstil_for_træk&slip_af_PDFer +Default_import_style_for_drag_and_drop_of_PDFs=Standard_importstil_for_træk&slip_af_PDFer Default_PDF_file_link_action=Standard_PDF_fillink-handling Filename_format_pattern=Filnavn-formatskabelon Additional_parameters=Yderligere_parametre @@ -1140,7 +1138,7 @@ Find_unlinked_files= Unselect_all= Expand_all= Collapse_all= -Choose_Directory= +Choose_directory= Use_the_selected_directory_to_start_with_the_search.= Opens_the_file_browser.= Scan_directory= @@ -1214,7 +1212,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.= Error_message\:= Created_group_"%0".= If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.= -Import_Metadata_From_PDF= +Import_metadata_from_PDF= Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.= Removed_all_subgroups_of_group_"%0".= To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.= @@ -1316,7 +1314,7 @@ Unmarked_selected_entry= Unmarked_all_entries= -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= @@ -1392,7 +1390,7 @@ OpenDocument_spreadsheet= OpenDocument_text= Please_move_the_file_manually_and_link_in_place.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Return_to_JabRef= @@ -1705,3 +1703,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 5b7fefc63192..052229cc30e6 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1244,7 +1244,7 @@ Select_file_from_ZIP-archive=Eintrag_aus_der_ZIP-Archiv_auswählen -Select_new_ImportFormat_Subclass=Klasse_auswählen +Select_new_ImportFormat_subclass=Klasse_auswählen Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Wählen_Sie_die_Verzweigungen_aus,_um_die_Änderungen_zu_sehen_und_anzunehmen_oder_zu_verwerfen Selected_entries=Ausgewählte_Einträge @@ -1261,7 +1261,6 @@ Set_table_font=Tabellenschriftart_auswählen Settings=Einstellungen -Setup_selectors=Wortlisten_verwalten Shortcut=Tastenkürzel @@ -1423,7 +1422,6 @@ This_group_contains_entries_whose_%0_field_contains_the_regular_expressio This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=JabRef_untersucht_damit_jeden_Datei-Link_und_überprüft,_ob_die_Datei_existiert._Falls_nicht,_werden_Ihnen_Optionen_gegeben,
    um_das_Problem_zu_lösen. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Für_diesen_Vorgang_müssen_alle_ausgewählen_Einträge_einen_BibTeX-Key_haben. -This_operation_requires_at_least_one_entry.=Dieser_Vorgang_benötigt_mindestens_einen_Eintrag. This_operation_requires_one_or_more_entries_to_be_selected.=Für_diesen_Vorgang_muss_mindestens_ein_Eintrag_ausgewählt_sein. @@ -1699,8 +1697,8 @@ Create_blank_entry_linking_the_PDF=Leeren_Eintrag_erstellen_mit_Link_zum_PDF Only_attach_PDF=Nur_PDF_anhängen Title=Titel No_internet_connection.=Keine_Internetverbindung. -Create_New_Entry=Neuen_Eintrag_erstellen -Update_Existing_Entry=Bestehenden_Eintrag_aktualisieren +Create_new_entry=Neuen_Eintrag_erstellen +Update_existing_entry=Bestehenden_Eintrag_aktualisieren Autocomplete_names_in_'Firstname_Lastname'_format_only=Automatische_Vervollständigung_von_Namen_nur_im_Format_'Vorname_Nachname' Autocomplete_names_in_'Lastname,_Firstname'_format_only=Automatische_Vervollständigung_von_Namen_nur_im_Format_'Nachname,_Vorname' Autocomplete_names_in_both_formats=Automatische_Vervollständigung_von_Namen_in_beiden_Formaten @@ -1721,7 +1719,7 @@ exportFormat=Exportformat Output_file_missing=Ausgabedatei_fehlt No_search_matches.=Keine_Übereinstimmungen_gefunden. The_output_option_depends_on_a_valid_input_option.=Die_Ausgabeoption_benötigt_eine_gültige_Eingabeoption. -Default_import_style_for_drag&drop_of_PDFs=Standard-Importstil_für_Drag&Drop_von_PDFs +Default_import_style_for_drag_and_drop_of_PDFs=Standard-Importstil_für_Drag&Drop_von_PDFs Default_PDF_file_link_action=Standardaktion_für_PDF-Dateiverweise Filename_format_pattern=Formatmuster_für_Dateinamen Additional_parameters=Weitere_Parameter @@ -1847,7 +1845,7 @@ Find_unlinked_files=Nicht_verlinkte_Dateien_finden Unselect_all=Auswahl_aufheben Expand_all=Alle_aufklappen Collapse_all=Alle_einklappen -Choose_Directory=Ordner_wählen +Choose_directory=Ordner_wählen Use_the_selected_directory_to_start_with_the_search.=Den_ausgewählten_Ordner_für_die_Suche_benutzen. Opens_the_file_browser.=Öffnet_den_Dateimanager. Scan_directory=Ordner_durchsuchen @@ -1922,7 +1920,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=Bei_manueller_V Error_message\:=Fehlermeldung\: Created_group_"%0".=Gruppe_"%0"_wurde_erstellt. If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=Falls_bei_einem_eingefügten_oder_importierten_Eintrag_das_Feld_bereits_belegt_ist,_überschreiben. -Import_Metadata_From_PDF=Metadaten_aus_PDF_importieren +Import_metadata_from_PDF=Metadaten_aus_PDF_importieren Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Keine_Verbindung_zu_einem_Writer-Dokument._Bitte_vergewissern_Sie_sich,_dass_ein_Dokument_geöffnet_ist,_und_benutzen_Sie_die_Schaltfläche_'Writer-Dokument_wählen',_um_eine_Verbindung_herzustellen. Removed_all_subgroups_of_group_"%0".=Alle_Untergruppen_der_Gruppe_"%0"_wurden_entfernt. To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Um_den_USB-Stick-Modus_zu_deaktivieren,_benennen_Sie_die_Datei_jabref.xml_in_demselben_Ordner_als_JabRef_oder_löschen_Sie_sie. @@ -2024,7 +2022,7 @@ Unmarked_selected_entry=Markierung_für_ausgewählten_Eintrag_aufgehoben Unmarked_all_entries=Markierung_für_alle_Einträge_aufgehoben -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Look_&_Feel_konnte_nicht_gefunden_werden,_stattdessen_wird_der_Standard_verwendet. +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Look_and_feel_konnte_nicht_gefunden_werden,_stattdessen_wird_der_Standard_verwendet. Could_not_open_browser.=Konnte_Browser_nicht_öffnen. Opens_JabRef's_GitHub_page=Öffnet_JabRefs_GitHub-Seite @@ -2102,7 +2100,7 @@ OpenDocument_spreadsheet=OpenDocument-Tabelle OpenDocument_text=OpenDocument-Text Please_move_the_file_manually_and_link_in_place.=Bitte_die_Datei_manuell_verschieben_und_verlinken. Print_entry_preview=Eintragsvorschau_drucken -Really_delete_the_selected_%0_entries?=Wirklich_alle_%0_ausgewählten_Einträge_löschen? +Really_delete_the_%0_selected_entries?=Wirklich_alle_%0_ausgewählten_Einträge_löschen? Really_delete_the_selected_entry?=Ausgewählten_Eintrag_wirklich_löschen? Removed_all_groups=Alle_Gruppen_entfernt Return_to_JabRef=Zurück_zu_JabRef @@ -2422,3 +2420,5 @@ Please_open_%0_manually.=Bitte_öffnen_Sie_%0_manuell. The_link_has_been_copied_to_the_clipboard.=Der_Link_wurde_in_die_Zwischenablage_kopiert. Online_help_forum=Online-Hilfeforum + +Custom= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index a85ebc531260..ec285564a4f6 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1173,7 +1173,7 @@ Select_external_application=Select_external_application Select_file_from_ZIP-archive=Select_file_from_ZIP-archive -Select_new_ImportFormat_Subclass=Select_new_ImportFormat_Subclass +Select_new_ImportFormat_subclass=Select_new_ImportFormat_subclass Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Select_the_tree_nodes_to_view_and_accept_or_reject_changes Selected_entries=Selected_entries @@ -1189,8 +1189,6 @@ Set_table_font=Set_table_font Settings=Settings -Setup_selectors=Setup_selectors - Shortcut=Shortcut Show/edit_BibTeX_source=Show/edit_BibTeX_source @@ -1339,7 +1337,6 @@ This_group_contains_entries_whose_%0_field_contains_the_regular_expressio This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined. -This_operation_requires_at_least_one_entry.=This_operation_requires_at_least_one_entry. This_operation_requires_one_or_more_entries_to_be_selected.=This_operation_requires_one_or_more_entries_to_be_selected. @@ -1599,8 +1596,8 @@ Create_blank_entry_linking_the_PDF=Create_blank_entry_linking_the_PDF Only_attach_PDF=Only_attach_PDF Title=Title No_internet_connection.=No_internet_connection. -Create_New_Entry=Create_New_Entry -Update_Existing_Entry=Update_Existing_Entry +Create_new_entry=Create_new_entry +Update_existing_entry=Update_existing_entry Autocomplete_names_in_'Firstname_Lastname'_format_only=Autocomplete_names_in_'Firstname_Lastname'_format_only Autocomplete_names_in_'Lastname,_Firstname'_format_only=Autocomplete_names_in_'Lastname,_Firstname'_format_only Autocomplete_names_in_both_formats=Autocomplete_names_in_both_formats @@ -1621,7 +1618,7 @@ exportFormat=exportFormat Output_file_missing=Output_file_missing No_search_matches.=No_search_matches. The_output_option_depends_on_a_valid_input_option.=The_output_option_depends_on_a_valid_input_option. -Default_import_style_for_drag&drop_of_PDFs=Default_import_style_for_drag&drop_of_PDFs +Default_import_style_for_drag_and_drop_of_PDFs=Default_import_style_for_drag_and_drop_of_PDFs Default_PDF_file_link_action=Default_PDF_file_link_action Filename_format_pattern=Filename_format_pattern Additional_parameters=Additional_parameters @@ -1747,7 +1744,7 @@ Find_unlinked_files=Find_unlinked_files Unselect_all=Unselect_all Expand_all=Expand_all Collapse_all=Collapse_all -Choose_Directory=Choose_Directory +Choose_directory=Choose_directory Use_the_selected_directory_to_start_with_the_search.=Use_the_selected_directory_to_start_with_the_search. Opens_the_file_browser.=Opens_the_file_browser. Scan_directory=Scan_directory @@ -1821,7 +1818,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=If_connecting_m Error_message\:=Error_message\: Created_group_"%0".=Created_group_"%0". If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite. -Import_Metadata_From_PDF=Import_Metadata_From_PDF +Import_metadata_from_PDF=Import_metadata_from_PDF Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it. Removed_all_subgroups_of_group_"%0".=Removed_all_subgroups_of_group_"%0". To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef. @@ -1931,7 +1928,7 @@ Toggle_print_status=Toggle_print_status Unmarked_all_entries=Unmarked_all_entries -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used. +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used. Opens_JabRef's_GitHub_page=Opens_JabRef's_GitHub_page Could_not_open_browser.=Could_not_open_browser. @@ -1990,7 +1987,7 @@ Added_new_'%0'_entry.=Added_new_'%0'_entry. Multiple_entries_selected._Do_you_want_to_change_the_type_of_all_these_to_'%0'?=Multiple_entries_selected._Do_you_want_to_change_the_type_of_all_these_to_'%0'? Changed_type_to_'%0'_for=Changed_type_to_'%0'_for Really_delete_the_selected_entry?=Really_delete_the_selected_entry? -Really_delete_the_selected_%0_entries?=Really_delete_the_selected_%0_entries? +Really_delete_the_%0_selected_entries?=Really_delete_the_%0_selected_entries? Keep_merged_entry_only=Keep_merged_entry_only Keep_left=Keep_left Keep_right=Keep_right @@ -2274,4 +2271,5 @@ To_see_what's_new_view_the_changelog.=To_see_what's_new_view_the_changelog. A_new_version_of_JabRef_has_been_released.=A_new_version_of_JabRef_has_been_released. JabRef_is_up-to-date.=JabRef_is_up-to-date. Latest_version=Latest_version -Online_help_forum=Online_help_forum \ No newline at end of file +Online_help_forum=Online_help_forum +Custom=Custom \ No newline at end of file diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 9be684ebbdbb..9d3e2fedf28f 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -625,7 +625,7 @@ Select_encoding=Seleccionar_codificación Select_entry_type=Seleccionar_tipo_de_entrada Select_external_application=Seleccionar_aplicación_externa Select_file_from_ZIP-archive=Seleccionar_archivo_desde_archivo_ZIP -Select_new_ImportFormat_Subclass=Seleccionar_nueva_subclase_de_formato_de_importación +Select_new_ImportFormat_subclass=Seleccionar_nueva_subclase_de_formato_de_importación Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Seleccionar_nodos_de_árbol_para_ver_y_aceptar_o_rechazar_los_cambios. Selected_entries=Entradas_seleccionadas Server_hostname=Nombre_de_host_del_servidor @@ -636,7 +636,6 @@ Set_general_fields=Establecer_campos_generales Set_main_external_file_directory=Establecer_carpeta_de_archivo_externo_principal Set_table_font=Establecer_tipo_dera_para_las_tablas Settings=Ajustes -Setup_selectors=Configurar_selectores Shortcut=Atajo Show/edit_BibTeX_source=Mostrar/editar_fuente_BibTeX Show_'Firstname_Lastname'=Mostrar_'Nombre_Apellido' @@ -715,7 +714,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Este_grupo_contiene_entradas_cuyo_campo_%0_contiene_la<_expresión_regular_%1_ This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=JabRef_inspeccionará_cada_enlace_archivo_y_comprobará_si_el_archivo_existe._En_caso_contrario,_se_le_ofrecerán_opciones_
    _para_solucionar_el_problema. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Esta_operación_requiere_que_todas_las_entradas_seleccionadas_tengan_claves_BibTeX_definidas. -This_operation_requires_at_least_one_entry.=Esta_operación_requiere_como_mínimo_una_entrada. This_operation_requires_one_or_more_entries_to_be_selected.=Esta_operación_requiere_seleccionar_una_o_más_entradas. Toggle_abbreviation=Usar_abreviatura_si/no Toggle_entry_preview=Usar_vista_previa_de_la_entrada_si/no @@ -910,8 +908,8 @@ Create_blank_entry_linking_the_PDF=Crear_entrada_en_blanco_enlazando_el_PDF Only_attach_PDF=Sólo_adjnntar_PDF Title=Título No_internet_connection.=_Sin_conexión_a_Internet. -Create_New_Entry=Crear_nueva_entrada -Update_Existing_Entry=Actualizar_entrada_existente +Create_new_entry=Crear_nueva_entrada +Update_existing_entry=Actualizar_entrada_existente Autocomplete_names_in_'Firstname_Lastname'_format_only=Autocompletar_nombres_sólo_en_el_formato_'Nombre_Apellidos' Autocomplete_names_in_'Lastname,_Firstname'_format_only=Autocompletar_nombres_sólo_en_el_formato_'Apellidos,_Nombre' Autocomplete_names_in_both_formats=Autocompletar_nombres_en_ambos_formatos @@ -932,7 +930,7 @@ exportFormat=Formato_de_exportación Output_file_missing=Fichero_de_salida_no_encontrado No_search_matches.=No_hay_coincidencias_en_la_búsqueda. The_output_option_depends_on_a_valid_input_option.=La_opción_de_salida_depende_de_una_opción_de_entrada_válida. -Default_import_style_for_drag&drop_of_PDFs=Estilo_de_importación_por_defecto_para_arrastrar-soltar_PDFs +Default_import_style_for_drag_and_drop_of_PDFs=Estilo_de_importación_por_defecto_para_arrastrar-soltar_PDFs Default_PDF_file_link_action=Acción_por_defecto_del_enlace_a_PDF Filename_format_pattern=Patrón_de_formato_de_nombre_de_archivo Additional_parameters=Parámetros_adicionales @@ -1050,7 +1048,7 @@ Find_unlinked_files=Buscar_archivos_desenlazados Unselect_all=Deseleccionar_todo Expand_all=Expandir_todo Collapse_all=Colapsar_todo -Choose_Directory=Escoger_directorio +Choose_directory=Escoger_directorio Use_the_selected_directory_to_start_with_the_search.=Usar_la_carpeta_seleccionada_para_comenzar_la_búsqueda. Opens_the_file_browser.=Abre_el_explorador_de_archivos. Scan_directory=Escanear_directorio @@ -1123,7 +1121,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=lf__connecting_ Error_message\:=Mensaje_de_error\: Created_group_"%0".=Creado_grupo_"%0". If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=Si_una_entrada_importada_o_pegada_ya_tiene_el_campo_establecido,_sobreescribir. -Import_Metadata_From_PDF=Importar_metadatos_desde_PDF +Import_metadata_from_PDF=Importar_metadatos_desde_PDF Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=No_conectado_a_ningún_documento_Writer._Asegúrese_de_que_un_documento_está_abierto_y_use_el_botón_"Seleccionar_documento_Writer'_para_conectar_con_él. Removed_all_subgroups_of_group_"%0".=Eliminados_todos_los_subgrupos_del_grupo_"%0". To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Para_deshabilitar_el_modo_lápiz_de_memoria,_renombre_o_elimine_el_archivo_jabrf.xml_en_la_misma_carpeta_que_JabRef. @@ -1217,7 +1215,7 @@ Unmarked_selected_entry=Entrada_seleccionada_desmarcada Unmarked_all_entries=Desmarcar_todas_las_entradas -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=No_se_puede_encontrar_el_aspecto_solicitado,_por_lo_que_se_usará_el_aspecto_por_defecto +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=No_se_puede_encontrar_el_aspecto_solicitado,_por_lo_que_se_usará_el_aspecto_por_defecto Could_not_open_browser.=No_se_puede_abrir_el_explorador. Opens_JabRef's_GitHub_page=Abrir_la_página_de_JabRef_en_GitHub @@ -1293,7 +1291,7 @@ OpenDocument_spreadsheet=Hoja_de_cálculo_OpenDocument OpenDocument_text=Texto_OpenDocument Please_move_the_file_manually_and_link_in_place.=Por_favor,_mueva_el_fichero_manualmente_y_enlance_en_el_destino Print_entry_preview=Imprimir_vista_previa_de_la_entrada -Really_delete_the_selected_%0_entries?=¿Realmente_desea_eliminar_%0_entradas? +Really_delete_the_%0_selected_entries?=¿Realmente_desea_eliminar_%0_entradas? Really_delete_the_selected_entry?=¿Borrar_realmente_la_entrada_seleccionada? Removed_all_groups=Se_eliminaron_todos_los_grupos Return_to_JabRef=Volver_a_JabRef @@ -1607,3 +1605,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 6a2a4b8f2a4d..a3f87222ddc0 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1207,7 +1207,7 @@ Select_file_from_ZIP-archive= -Select_new_ImportFormat_Subclass= +Select_new_ImportFormat_subclass= Select_the_tree_nodes_to_view_and_accept_or_reject_changes= Selected_entries= @@ -1223,7 +1223,6 @@ Set_table_font= Settings= -Setup_selectors= Shortcut= @@ -1381,7 +1380,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1= This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.= -This_operation_requires_at_least_one_entry.= This_operation_requires_one_or_more_entries_to_be_selected.= @@ -1655,8 +1653,8 @@ Create_blank_entry_linking_the_PDF= Only_attach_PDF= Title= No_internet_connection.= -Create_New_Entry= -Update_Existing_Entry= +Create_new_entry= +Update_existing_entry= Autocomplete_names_in_'Firstname_Lastname'_format_only= Autocomplete_names_in_'Lastname,_Firstname'_format_only= Autocomplete_names_in_both_formats= @@ -1677,7 +1675,7 @@ exportFormat= Output_file_missing= No_search_matches.= The_output_option_depends_on_a_valid_input_option.= -Default_import_style_for_drag&drop_of_PDFs= +Default_import_style_for_drag_and_drop_of_PDFs= Default_PDF_file_link_action= Filename_format_pattern= Additional_parameters= @@ -1802,7 +1800,7 @@ Find_unlinked_files= Unselect_all= Expand_all= Collapse_all= -Choose_Directory= +Choose_directory= Use_the_selected_directory_to_start_with_the_search.= Opens_the_file_browser.= Scan_directory= @@ -1876,7 +1874,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.= Error_message\:= Created_group_"%0".= If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.= -Import_Metadata_From_PDF= +Import_metadata_from_PDF= Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.= Removed_all_subgroups_of_group_"%0".= To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.= @@ -1980,7 +1978,7 @@ Toggle_print_status= Unmarked_all_entries= -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.= Opens_JabRef's_GitHub_page= Could_not_open_browser.= @@ -2068,7 +2066,7 @@ Path_to_%0= Please_move_the_file_manually_and_link_in_place.= Possible_duplicate_of_existing_entry._Click_to_resolve.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Return_to_JabRef= @@ -2393,3 +2391,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index d7b634d6a445..d6a27fbda496 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -625,7 +625,7 @@ Select_encoding=Sélectionner_l'encodage Select_entry_type=Sélectionner_un_type_d'entrée Select_external_application=Sélectionner_une_application_externe Select_file_from_ZIP-archive=Sélectionner_un_fichier_depuis_une_archive_ZIP -Select_new_ImportFormat_Subclass=Sélectionner_une_nouvelle_sous-classe_ImportFormat +Select_new_ImportFormat_subclass=Sélectionner_une_nouvelle_sous-classe_ImportFormat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Sélectionner_les_noeuds_de_l'arborescence_pour_voir,_et_accepter_ou_rejeter,_les_modifications Selected_entries=Les_entrées_sélectionnées Server_hostname=Nom_de_l'hôte_du_serveur @@ -636,7 +636,6 @@ Set_general_fields=Définir_les_champs_généraux Set_main_external_file_directory=Définir_le_répertoire_principal_des_fichiers_externes Set_table_font=Définir_la_police_de_la_table Settings=Paramètres -Setup_selectors=Gérer_les_sélecteurs Shortcut=Raccourci Show/edit_BibTeX_source=Montrer/éditer_le_source_BibTeX Show_'Firstname_Lastname'=Ordre_d'affichage_'Prénom_Nom' @@ -715,7 +714,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Ce_groupe_contient_des_entrées_dont_le_champ_%0_contient_l'expression_régulière_%1_ This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=JabRef_cherche_chaque_fichier_lien_et_vérifie_si_le_fichier_existe._Si_non,_des_options_vous_seront_proposées
    pour_résoudre_le_problème. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Cette_opération_nécessite_que_toutes_les_entrées_sélectionnées_aient_des_clefs_BibTeX_définies -This_operation_requires_at_least_one_entry.=Cette_opération_nécessite_au_moins_une_entrée. This_operation_requires_one_or_more_entries_to_be_selected.=Cette_opération_nécessite_qu'une_ou_plusieurs_entrées_soient_sélectionnées. Toggle_abbreviation=Afficher/Masquer_l'abréviation Toggle_entry_preview=Afficher/Masquer_l'aperçu @@ -929,8 +927,8 @@ Create_blank_entry_linking_the_PDF=Créer_une_entrée_vide_liée_au_PDF Only_attach_PDF=Lier_uniquement_le_PDF Title=Titre No_internet_connection.=_Pas_de_connexion_internet. -Create_New_Entry=Créer_une_nouvelle_entrée -Update_Existing_Entry=Mettre_à_jour_une_entrée_existante +Create_new_entry=Créer_une_nouvelle_entrée +Update_existing_entry=Mettre_à_jour_une_entrée_existante Autocomplete_names_in_'Firstname_Lastname'_format_only=Complétion_automatique_des_noms_uniquement_dans_le_format_'Prénom_Nom' Autocomplete_names_in_'Lastname,_Firstname'_format_only=Complétion_automatique_des_noms_uniquement_dans_le_format_'Nom,_Prénom' Autocomplete_names_in_both_formats=Complétion_automatique_des_noms_dans_les_2_formats @@ -952,7 +950,7 @@ exportFormat=Format_d'exportation Output_file_missing=Fichier_de_sortie_manquant No_search_matches.=Recherche_sans_correspondance. The_output_option_depends_on_a_valid_input_option.=L'option_de_sortie_dépend_d'une_option_d'entrée_valide. -Default_import_style_for_drag&drop_of_PDFs=Style_d'importation_par_défaut_pour_le_glisser-déplacer_des_PDFs +Default_import_style_for_drag_and_drop_of_PDFs=Style_d'importation_par_défaut_pour_le_glisser-déplacer_des_PDFs Default_PDF_file_link_action=Action_par_défaut_pour_les_liens_vers_les_fichiers_PDF Filename_format_pattern=Modèle_de_format_de_nom_de_fichier Additional_parameters=Paramètres_additionnels @@ -1080,7 +1078,7 @@ Find_unlinked_files=Trouver_les_fichiers_non_liés Unselect_all=Tout_désélectionner Expand_all=Tout_étendre Collapse_all=Tout_masquer -Choose_Directory=Choisir_un_répertoire +Choose_directory=Choisir_un_répertoire Use_the_selected_directory_to_start_with_the_search.=Utiliser_le_répertoire_sélectionné_pour_lancer_la_recherche. Opens_the_file_browser.=Ouvre_l'explorateur_de_fichier. Scan_directory=Examiner_le_répertoire @@ -1154,7 +1152,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=En_cas_de_conne Error_message\:=Message_d'erreur\: Created_group_"%0".=Groupe_"%0"_créé. If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=Si_une_entrée_collée_ou_importée_a_le_champ_déjà_paramétré,_écraser. -Import_Metadata_From_PDF=Importer_les_méta-données_à_partir_du_PDF +Import_metadata_from_PDF=Importer_les_méta-données_à_partir_du_PDF Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Pas_de_connexion_à_un_document_Writer._S'il_vous_plait,_assurez-vous_qu'un_document_est_ouvert_et_utiliser_le_bouton_'Sélectionner_un_document_Writer'_pour_vous_y_connecter. Removed_all_subgroups_of_group_"%0".=Tous_les_sous-groupes_du_groupe_"%0"_ont_été_supprimés. To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Pour_désactiver_le_mode_Memory-stick,_renommer_ou_supprimer_le_fichier_jabref.xml_dans_le_même_répertoire_que_JabRef @@ -1257,7 +1255,7 @@ Unmarked_selected_entry=Entrées_sélectionnées_désétiquetées Unmarked_all_entries=Toutes_les_entrées_désétiquetées -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Impossible_de_trouver_l'apparence_demandée._Aussi,_celle_par_défaut_est_utilisée. +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Impossible_de_trouver_l'apparence_demandée._Aussi,_celle_par_défaut_est_utilisée. Could_not_open_browser.=Le_navigateur_n'a_pas_pu_être_lancé. Opens_JabRef's_GitHub_page=Ouvre_la_page_GitHub_de_JabRef @@ -1332,7 +1330,7 @@ OpenDocument_spreadsheet=Tableau_OpenDocument OpenDocument_text=Texte_OpenDocument Please_move_the_file_manually_and_link_in_place.=Déplacez_le_fichier_manuellement_et_liez-le,_SVP. Print_entry_preview=Imprimer_la_prévisualisation_de_l'entrée -Really_delete_the_selected_%0_entries?=Voulez-vous_vraiment_supprimer_les_%0_entrées_sélectionnées_? +Really_delete_the_%0_selected_entries?=Voulez-vous_vraiment_supprimer_les_%0_entrées_sélectionnées_? Really_delete_the_selected_entry?=Voulez-vous_vraiment_supprimer_l'entrée_sélectionnée_? Removed_all_groups=Supprimer_tous_les_groupes Return_to_JabRef=Revenir_à_JabRef @@ -1651,3 +1649,5 @@ Please_open_%0_manually.=Ouvrez_%0_manuellement,_SVP. The_link_has_been_copied_to_the_clipboard.=Le_lien_a_été_copié_dans_le_presse-papiers. Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 4f57a4b8ecf3..1244bdaa5271 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -624,7 +624,7 @@ Select_encoding=Pilih_enkoding Select_entry_type=Pilih_tipe_entri Select_external_application=Pilih_aplikasi_eksternal Select_file_from_ZIP-archive=Pilih_berkas_dari_arsip_ZIP -Select_new_ImportFormat_Subclass=Pilih_ImportFormat_Subclass_baru +Select_new_ImportFormat_subclass=Pilih_ImportFormat_subclass_baru Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Pilih_tiga_nodal_untuk_melihat,_menerima_atau_menolak_perubahan Selected_entries=Entri_pilihan Server_hostname=Nama_Host_Server @@ -635,7 +635,6 @@ Set_general_fields=Pilih_bidang_umum Set_main_external_file_directory=Tetapkan_direktori_utama_berkas_eksternal Set_table_font=Tetapkan_huruf_tabel Settings=Pengaturan -Setup_selectors=Pengaturan_pengisian_kata Shortcut=Pintasan Show/edit_BibTeX_source=Tampil/Sunting_sumber_BibTeX Show_'Firstname_Lastname'=Tampil_'Depan_Belakang' @@ -714,7 +713,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Grup_ini_memiliki_entri_dimana_bidang_%0_mempunyai_ekspresi_reguler_%1 This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Ini_membuat_JabRef_mencari_disemua_tautan_berkas_dan_memeriksa_apakah_ada_berkas._Jika_tidak,_anda_diberi_pilihan_
    untuk_mengatasi_masalah. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Operasi_ini_memerlukan_semua_entri_mempunyai_kunci_BibTeX. -This_operation_requires_at_least_one_entry.=Operasi_ini_memerlukan_paling_tidak_satu_entri. This_operation_requires_one_or_more_entries_to_be_selected.=Operasi_ini_memerlukan_satu_atau_lebih_entri_yang_dipilih. Toggle_abbreviation=Gunakan_singkatan Toggle_entry_preview=Gunakan_pratampilan_entri @@ -910,8 +908,8 @@ Create_blank_entry_linking_the_PDF=Membuat_entri_kosong_tautan_PDF Only_attach_PDF=Hanya_lampirkan_PDF Title=Judul No_internet_connection.=Konesksi_Internet_Tidak_Ada. -Create_New_Entry=membuat_Entri_Baru -Update_Existing_Entry=Perbarui_Entri_Yang_Sudah_Ada +Create_new_entry=membuat_Entri_Baru +Update_existing_entry=Perbarui_Entri_Yang_Sudah_Ada Autocomplete_names_in_'Firstname_Lastname'_format_only=Nama_isian_otomatis_hanya_untuk_format_'Namadepan_Namaakhir' Autocomplete_names_in_'Lastname,_Firstname'_format_only=Nama_isian_otomatis_hanya_untuk_format_'Namaakhir,_Namadepan' Autocomplete_names_in_both_formats=Nama_isian_otomatis_untuk_kedua_format @@ -932,7 +930,7 @@ exportFormat=FormatEkspor Output_file_missing=Berkas_keluaran_hilang No_search_matches.=Carian_tidak_ditemukan. The_output_option_depends_on_a_valid_input_option.=Pilihan_keluaran_tergantung_dari_pilihan_masukan_yang_tepat. -Default_import_style_for_drag&drop_of_PDFs=Gaya_impor_bawaan_PDF_untuk_seret_dan_masuk +Default_import_style_for_drag_and_drop_of_PDFs=Gaya_impor_bawaan_PDF_untuk_seret_dan_masuk Default_PDF_file_link_action=Aksi_tautan_PDF_bawaan Filename_format_pattern=Pola_format_nama_berkas Additional_parameters=Parameter_tambahan @@ -1058,7 +1056,7 @@ Find_unlinked_files=Temukan_berkas_yang_tidak_bertautan Unselect_all=Tidak_memilih_semua Expand_all= Collapse_all= -Choose_Directory=Pilih_direktori +Choose_directory=Pilih_direktori Use_the_selected_directory_to_start_with_the_search.=Gunakan_direktori_polihan_untuk_memulai_pencarian. Opens_the_file_browser.=Buka_penjelajah_berkas. Scan_directory=Pindai_direktori @@ -1131,7 +1129,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=Kalau_menyambun Error_message\:=Pesan_kesalahan\: Created_group_"%0".=Grup_"%0"_dibuat. If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.= -Import_Metadata_From_PDF=Impor_metadata_dari_PDF +Import_metadata_from_PDF=Impor_metadata_dari_PDF Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Tidak_tersambung_dengan_dokumen_Writer._Pastikan_salah_satu_dokumen_terbuka_dan_gunakan_tombol_'Select_Writer_document'_untuk_menyambung_dengan_dokumen_itu. Removed_all_subgroups_of_group_"%0".=Semua_anak_grup_dari_grup_"%0"_dihapus. To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Untuk_mengtidakaktifkan_mode_pena_simpan_ubah_atau_hapus_berkas_jabref.xml_dalam_direktori_yang_sama_dengan_JabRef. @@ -1234,7 +1232,7 @@ Unmarked_selected_entry=Tanda_entri_pilihan_dihilangkan Unmarked_all_entries=Tanda_semua_entri_dihilangkan -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Penampilan_yang_dimintai_tidak_bisa_ditemukan._Karena_begitu,_penampilan_bawaan_akan_digunakan. +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Penampilan_yang_dimintai_tidak_bisa_ditemukan._Karena_begitu,_penampilan_bawaan_akan_digunakan. Could_not_open_browser.=Penjelajah_tidak_bisa_dibuka. Opens_JabRef's_GitHub_page=Buka_halaman_JabRef_di_GitHub @@ -1310,7 +1308,7 @@ OpenDocument_spreadsheet=Lembatang_lajur_OpenDocument OpenDocument_text=Teks_OpenDocument Please_move_the_file_manually_and_link_in_place.=Silahkan_memindah_berkas_secara_manual_dan_menautkan_tempatnya. Print_entry_preview=Cetak_pratinjau_entri -Really_delete_the_selected_%0_entries?=Apa_benar-benar_mau_menghapus_%0_entri_yang_dipilih? +Really_delete_the_%0_selected_entries?=Apa_benar-benar_mau_menghapus_%0_entri_yang_dipilih? Really_delete_the_selected_entry?=Apa_benar-benar_mau_menghapus_entri_pilihan? Removed_all_groups=Semua_kelompok_dihapus Return_to_JabRef=Kembali_ke_JabRef @@ -1626,3 +1624,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index fa88dc92320f..0eacdd6589de 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -681,7 +681,7 @@ Select_encoding=Seleziona_la_codifica Select_entry_type=Seleziona_un_tipo_di_voce Select_external_application=Seleziona_un'applicazione_esterna Select_file_from_ZIP-archive=Seleziona_un_file_da_un_archivio_Zip -Select_new_ImportFormat_Subclass=Seleziona_una_nuova_sottoclasse_ImportFormat +Select_new_ImportFormat_subclass=Seleziona_una_nuova_sottoclasse_ImportFormat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Selezionare_i_nodi_dell'albero_per_vedere_ed_accettare_o_rifiutare_le_modifiche Selected_entries=Voci_selezionate Server_hostname=Hostname_del_server @@ -694,7 +694,6 @@ Set_main_external_file_directory=Impostare_la_cartella_principale_dei_file_ester Set_table_font=Definisci_i_font_della_tabella Settings=Parametri ##_check -Setup_selectors=Definisci_i_selettori Shortcut=Scorciatoia Show/edit_BibTeX_source=Mostra/Modifica_codice_sorgente_BibTeX Show_'Firstname_Lastname'=Mostra_'Nome_Cognome' @@ -779,7 +778,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Questo_gruppo_contiene_voci_in_cui_il_campo_%0__contiene_l'espressione_regolare_%1 This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Per_ciascuno_dei_file_collegamenti,_JabRef_verificher\u00e0_l'esistenza_del_file.
    In_caso_negativo_proporr\u00e0_delle_opzioni_per_la_risoluzione_del_problema. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Per_questa_operazione_\u00e8_necessario_che_tutte_le_voci_selezionate_abbiano_la_chiave_BibTeX_definita -This_operation_requires_at_least_one_entry.=Questa_operazione_richiede_almeno_una_voce. This_operation_requires_one_or_more_entries_to_be_selected.=Per_questa_operazione_una_o_pi\u00f9_voci_devono_essere_selezionate Toggle_abbreviation=Mostra/Nascondi_l'abbreviazione Toggle_entry_preview=Mostra/Nascondi_l'anteprima @@ -1007,8 +1005,8 @@ Create_blank_entry_linking_the_PDF=Crea_una_voce_vuota_collegata_al_file_PDF Only_attach_PDF=Allega_solo_il_file_PDF Title=Titolo No_internet_connection.=Nessuna_connessione_a_Internet. -Create_New_Entry=Crea_una_nuova_voce -Update_Existing_Entry=Aggiorna_la_voce_esistente +Create_new_entry=Crea_una_nuova_voce +Update_existing_entry=Aggiorna_la_voce_esistente Autocomplete_names_in_'Firstname_Lastname'_format_only=Autocompletamento_dei_nomi_solo_nel_formato_'Firstname_Lastname' Autocomplete_names_in_'Lastname,_Firstname'_format_only=Autocompletamento_dei_nomi_solo_nel_formato_'Lastname,_Firstname' Autocomplete_names_in_both_formats=Autocompletamento_dei_nomi_in_entrambi_i_formati @@ -1029,7 +1027,7 @@ exportFormat=Formato_di_esportazione Output_file_missing=File_di_output_mancante No_search_matches.=Nessuna_corrispondenza_per_la_ricerca. The_output_option_depends_on_a_valid_input_option.=L'opzione_di_output_dipende_da_un'opzione_di_input_valida. -Default_import_style_for_drag&drop_of_PDFs=Modalit\u00e0_di_importazione_predefinita_per_il_drag&drop_dei_file_PDF +Default_import_style_for_drag_and_drop_of_PDFs=Modalit\u00e0_di_importazione_predefinita_per_il_drag_and_drop_dei_file_PDF Default_PDF_file_link_action=Azione_predefinita_per_il_collegamento_ai_file_PDF Filename_format_pattern=Modello_del_formato_dei_nomi_dei_file Additional_parameters=Parametri_addizionali @@ -1156,7 +1154,7 @@ Find_unlinked_files=Trovati_file_non_collegati Unselect_all=Deseleziona_tutto Expand_all=Espandi_tutto Collapse_all=Comprimi_tutto -Choose_Directory=Scegli_cartella +Choose_directory=Scegli_cartella Use_the_selected_directory_to_start_with_the_search.=Usa_la_cartella_selezionata_per_iniziare_la_ricerca. Opens_the_file_browser.=Apre_il_dialogo_di_selezione_dei_file. Scan_directory=Analizza_la_cartella @@ -1232,7 +1230,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=Se_si_effettua_ Error_message\:=Messaggio_di_errore\: Created_group_"%0".=Creato_il_gruppo_"%0". If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=Se_la_voce_incollata_o_importata_ha_il_campo_gi\u00e0_impostato,_sovrascrivere. -Import_Metadata_From_PDF=Importa_metadati_dal_file_PDF +Import_metadata_from_PDF=Importa_metadati_dal_file_PDF Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Non_connesso_ad_alcun_documento_Writer._Assicurarsi_che_un_documento_sia_aperto_e_connetterlo_con_il_bottone_"Selezionare_il_documento_Writer". Removed_all_subgroups_of_group_"%0".=Eliminati_tutti_i_sottogruppi_del_gruppo_"%0". To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Per_disabilitare_la_modalit\u00e0_chiavetta_di_memoria_rinominare_o_cancellare_il_file_"jabref.xml"_che_si_trova_nella_cartella_di_installazione_di_JabRef. @@ -1334,7 +1332,7 @@ Unmarked_selected_entry=Rimossi_i_contrassegni_dalle_voci_selezionate Unmarked_all_entries=Rimossi_i_contrassegni_da_tutte_voci -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Impossibile_trovare_il_'Look_&_Feel'_richiesto._Viene_utilizzato_quello_predefinito +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Impossibile_trovare_il_'look_and_feel'_richiesto._Viene_utilizzato_quello_predefinito Could_not_open_browser.=Impossibile_avviare_il_browser Opens_JabRef's_GitHub_page=Apri_la_pagina_di_JabRef_su_GitHub @@ -1410,7 +1408,7 @@ OpenDocument_spreadsheet= OpenDocument_text= Please_move_the_file_manually_and_link_in_place.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Return_to_JabRef= @@ -1726,3 +1724,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 066320369067..19b1299db632 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1225,7 +1225,7 @@ Select_file_from_ZIP-archive=ZIP書庫からファイルを選択してくださ -Select_new_ImportFormat_Subclass=新しいImportFormatサブクラスを選択 +Select_new_ImportFormat_subclass=新しいImportFormatサブクラスを選択 Select_the_tree_nodes_to_view_and_accept_or_reject_changes=ツリーノードを選択して表示させ、変更を受諾ないし拒否してください Selected_entries=選択した項目 @@ -1241,7 +1241,6 @@ Set_table_font=表フォントを設定 Settings=設定 -Setup_selectors=選択メニューを設定 Shortcut=捷径(ショートカット) @@ -1404,7 +1403,6 @@ This_group_contains_entries_whose_%0_field_contains_the_regular_expressio This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=これを有効にすると、JabRefは各ファイルリンクを調べ、ファイルが存在するかどうか確認します。
    もし存在しなければ、問題を解決する選択肢を提供します。 This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=この操作を行うには、選択された全項目にBibTeX鍵が定義されている必要があります。 -This_operation_requires_at_least_one_entry.=この操作を行うには、1つ以上の項目が必要です。 This_operation_requires_one_or_more_entries_to_be_selected.=この操作を行うには、1つ以上の項目が選択されている必要があります。 @@ -1683,8 +1681,8 @@ Create_blank_entry_linking_the_PDF=PDFにリンクした空の項目を生成 Only_attach_PDF=PDFを添付してください Title=タイトル No_internet_connection.=インターネットに接続されていません。 -Create_New_Entry=新規項目を作成 -Update_Existing_Entry=既存項目を更新 +Create_new_entry=新規項目を作成 +Update_existing_entry=既存項目を更新 Autocomplete_names_in_'Firstname_Lastname'_format_only=「名_姓」形式の名前のみ自動補完 Autocomplete_names_in_'Lastname,_Firstname'_format_only=「姓,_名」形式の名前のみ自動補完 Autocomplete_names_in_both_formats=両方の形式とも自動補完 @@ -1705,7 +1703,7 @@ exportFormat=exportFormat Output_file_missing=出力ファイルが見当たりません No_search_matches.=検索条件に一致するものがありませんでした。 The_output_option_depends_on_a_valid_input_option.=出力オプションは、入力オプションのうち、有効なものに依存します。 -Default_import_style_for_drag&drop_of_PDFs=PDFファイルのドラッグ&ドロップに対する読み込み方法の既定値 +Default_import_style_for_drag_and_drop_of_PDFs=PDFファイルのドラッグ&ドロップに対する読み込み方法の既定値 Default_PDF_file_link_action=PDFファイルのリンク方法の既定値 Filename_format_pattern=ファイル名の書式パターン Additional_parameters=追加のパラメーター @@ -1829,7 +1827,7 @@ Find_unlinked_files=リンクしていないファイルを検索 Unselect_all=すべての選択を解除 Expand_all=すべて展開表示 Collapse_all=すべて畳んで表示 -Choose_Directory=辞書を選ぶ +Choose_directory=辞書を選ぶ Use_the_selected_directory_to_start_with_the_search.=選択したディレクトリから検索を開始します。 Opens_the_file_browser.=ファイルブラウザを開きます Scan_directory=ディレクトリを走査 @@ -1903,7 +1901,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=手動で接続 Error_message\:=エラーメッセージは以下の通り\: Created_group_"%0".=グループ「%0」を作成しました。 If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=既にフィールドセットのある項目を貼り付けたり読み込んだりした場合には、上書きする。 -Import_Metadata_From_PDF=PDFからMetadataを読み込む +Import_metadata_from_PDF=PDFからMetadataを読み込む Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=どのWriter文書にも接続されていません。文書が開かれているか確認して、「Writer文書を選択」ボタンを押して接続してください。 Removed_all_subgroups_of_group_"%0".=グループ「%0」の全下層グループを削除しました To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=メモリースティックモードを無効にするには、JabRefと同じフォルダにあるjabref.xmlファイルを改名するか削除してください @@ -2005,7 +2003,7 @@ Unmarked_selected_entry=選択項目の標識を外しました Unmarked_all_entries=全項目の標識を外しました -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=要求のあった操作性設定を見つけることができなかったので、既定値を使用します。 +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=要求のあった操作性設定を見つけることができなかったので、既定値を使用します。 Could_not_open_browser.=ブラウザを開くことができませんでした。 Opens_JabRef's_GitHub_page=JabRefのGitHubページを開きます @@ -2082,7 +2080,7 @@ OpenDocument_spreadsheet=OpenDocument表計算 OpenDocument_text=OpenDocument文書 Please_move_the_file_manually_and_link_in_place.=ファイルを手動で移動して、そこでリンクしてください。 Print_entry_preview=項目プレビューを印刷 -Really_delete_the_selected_%0_entries?=選択した%0項目を本当に削除しますか? +Really_delete_the_%0_selected_entries?=選択した%0項目を本当に削除しますか? Really_delete_the_selected_entry?=選択した項目を本当に削除しますか? Removed_all_groups=全グループを削除しました Return_to_JabRef=JabRefに戻る @@ -2371,3 +2369,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 2cb522bb728a..87a6882a5c8b 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1242,7 +1242,7 @@ Select_file_from_ZIP-archive=Selecteer_bestand_van_ZIP-archief -Select_new_ImportFormat_Subclass=Selecteer_nieuw_ImportFormat_Subklasse +Select_new_ImportFormat_subclass=Selecteer_nieuw_ImportFormat_Subklasse Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Selecteer_de_boom_knopen_om_veranderingen_te_tonen_en_te_accepteren_of_afwijzen Selected_entries=Geselecteerde_entries @@ -1259,7 +1259,6 @@ Set_table_font=Tabel_lettertype_instellen Settings=Instellingen -Setup_selectors=Selectors_instellen Shortcut=Snelkoppeling @@ -1421,7 +1420,6 @@ This_group_contains_entries_whose_%0_field_contains_the_regular_expressio This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Dit_zorgt_ervoor_dat_JabRef_elke_bestand_snelkoppeling_op_zoekt_en_controleert_of_het_bestand_bestaat._Indien_dit_niet_het_geval_is,_zullen_u_opties_gegeven_worden
    om_het_probleem_op_te_lossen. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Deze_operatie_vereist_dat_alle_geselecteerde_entries_BibTeX-sleutels_gedefinieerd_hebben. -This_operation_requires_at_least_one_entry.= This_operation_requires_one_or_more_entries_to_be_selected.=Deze_operatie_vereist_dat_een_of_meer_entries_geselecteerd_zijn. @@ -1684,8 +1682,8 @@ Create_blank_entry_linking_the_PDF= Only_attach_PDF= Title= No_internet_connection.= -Create_New_Entry= -Update_Existing_Entry= +Create_new_entry= +Update_existing_entry= Autocomplete_names_in_'Firstname_Lastname'_format_only= Autocomplete_names_in_'Lastname,_Firstname'_format_only= Autocomplete_names_in_both_formats= @@ -1706,7 +1704,7 @@ exportFormat= Output_file_missing= No_search_matches.= The_output_option_depends_on_a_valid_input_option.= -Default_import_style_for_drag&drop_of_PDFs= +Default_import_style_for_drag_and_drop_of_PDFs= Default_PDF_file_link_action= Filename_format_pattern= Additional_parameters= @@ -1831,7 +1829,7 @@ Find_unlinked_files= Unselect_all= Expand_all= Collapse_all= -Choose_Directory= +Choose_directory= Use_the_selected_directory_to_start_with_the_search.= Opens_the_file_browser.= Scan_directory= @@ -1905,7 +1903,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.= Error_message\:= Created_group_"%0".= If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.= -Import_Metadata_From_PDF= +Import_metadata_from_PDF= Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.= Removed_all_subgroups_of_group_"%0".= To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.= @@ -2007,7 +2005,7 @@ Unmarked_selected_entry= Unmarked_all_entries= -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= @@ -2083,7 +2081,7 @@ OpenDocument_text= Path_to_%0= Please_move_the_file_manually_and_link_in_place.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Return_to_JabRef= @@ -2402,3 +2400,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 903c290d7316..fc415c1ced27 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1332,7 +1332,7 @@ Select_file_from_ZIP-archive=Velg_fil_fra_ZIP-fil -Select_new_ImportFormat_Subclass=Velg_klasse_for_nytt_importformat +Select_new_ImportFormat_subclass=Velg_klasse_for_nytt_importformat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Velg_trenodene_for_\u00e5_inspisere_og_akseptere_eller_avsl\u00e5_endringer @@ -1354,7 +1354,6 @@ Set_table_font=Velg_tabellfont Settings=Innstillinger -Setup_selectors=Sett_opp_ordlister Shortcut=Snarvei @@ -1526,7 +1525,6 @@ This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_y This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Denne_operasjonen_krever_at_alle_valgte_enheter_har_definerte_BibTeX-n\u00f8kler. -This_operation_requires_at_least_one_entry.=Denne_operasjonen_krever_minst_en_enhet. This_operation_requires_one_or_more_entries_to_be_selected.=Denne_operasjonen_krever_at_en_eller_flere_enheter_er_valgt. @@ -1964,9 +1962,9 @@ Title=Tittel No_internet_connection.=Ingen_internettforbindelse -Create_New_Entry=Lag_ny_enhet +Create_new_entry=Lag_ny_enhet -Update_Existing_Entry=Oppdater_eksisterende_enhet +Update_existing_entry=Oppdater_eksisterende_enhet Autocomplete_names_in_'Firstname_Lastname'_format_only=Autokompletter_navn_i_'Fornavn_Etternavn'-format @@ -2008,7 +2006,7 @@ No_search_matches.=Ingen_s\u00f8keresultater The_output_option_depends_on_a_valid_input_option.=Output-innstillingen_krever_en_gyldig_input-innstilling -Default_import_style_for_drag&drop_of_PDFs=Standard_importmetode_for_PDF-filer +Default_import_style_for_drag_and_drop_of_PDFs=Standard_importmetode_for_PDF-filer Default_PDF_file_link_action=Standardaksjon_for_PDF-fillinker @@ -2227,7 +2225,7 @@ Find_unlinked_files= Unselect_all= Expand_all= Collapse_all= -Choose_Directory= +Choose_directory= Use_the_selected_directory_to_start_with_the_search.= Opens_the_file_browser.= Scan_directory= @@ -2300,7 +2298,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.= Error_message\:= Created_group_"%0".= If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.= -Import_Metadata_From_PDF= +Import_metadata_from_PDF= Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.= Removed_all_subgroups_of_group_"%0".= To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.= @@ -2402,7 +2400,7 @@ Unmarked_selected_entry= Unmarked_all_entries= -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= @@ -2479,7 +2477,7 @@ OpenDocument_spreadsheet= OpenDocument_text= Please_move_the_file_manually_and_link_in_place.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Return_to_JabRef= @@ -2798,3 +2796,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index c6b952611447..d48b41bf999d 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -625,7 +625,7 @@ Select_encoding=Selecionar_codificação Select_entry_type=Selecionar_tipo_de_referência Select_external_application=Selecionar_aplicação_externa Select_file_from_ZIP-archive=Selecionar_arquivo_a_partir_de_um_arquivo_ZIP -Select_new_ImportFormat_Subclass=Selecionar_nova_subclasse_ImportFormat +Select_new_ImportFormat_subclass=Selecionar_nova_subclasse_ImportFormat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Selecione_os_nós_da_árvore_para_visualizar_e_aceitar_ou_rejeitar_mudanças Selected_entries=Referências_selecionadas Server_hostname=Hostname_do_servidor @@ -636,7 +636,6 @@ Set_general_fields=Definir_campos_gerais Set_main_external_file_directory=Definir_diretório_principal_de_arquivo_externo Set_table_font=Definir_fonte_da_tabela Settings=Configurações -Setup_selectors=Configurar_seletores Shortcut=Atalho Show/edit_BibTeX_source=Exibir/editar_fonte_BibTeX Show_'Firstname_Lastname'=Exibir_'Nome,_Sobrenome' @@ -715,7 +714,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Este_grupo_contém_referências_cujo_campo_%0_contém_a_expressão_regular_%1 This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Isto_faz_com_que_o_JabRed_busque_cada_link_de arquivos_e_verifique_se_o_arquivo_existe._Caso_não_exista,_serão_exibidas_opções
    _para_resolver_o_problema. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Esta_operação_requer_que_todas_as_referências_selecionadas_tenham_chaves_BibTeX_definidas. -This_operation_requires_at_least_one_entry.=Esta_operação_requer_ao_menos_uma_referência. This_operation_requires_one_or_more_entries_to_be_selected.=Esta_operação_exige_que_uma_ou_mais_referências_sejam_selecionadas Toggle_abbreviation=Habilitar/Desabilitar_abreviação Toggle_entry_preview=Habilitar/Desabilitar_previsualização_da_referência @@ -909,8 +907,8 @@ Create_blank_entry_linking_the_PDF=Criar_referência_em_branco_linkando_o_PDF Only_attach_PDF=Anexar_apenas_PDF Title=Título No_internet_connection.=Sem_conexão_com_a_internet. -Create_New_Entry=Criar_nova_referência -Update_Existing_Entry=Atualizar_referência_existente +Create_new_entry=Criar_nova_referência +Update_existing_entry=Atualizar_referência_existente Autocomplete_names_in_'Firstname_Lastname'_format_only=Autocompletar_nome_em_um_formato_'Nome,_Sobrenome'_apenas Autocomplete_names_in_'Lastname,_Firstname'_format_only=Autocompletar_nomes_em_um_formato_'Sobrenome,_Nome'_apenas Autocomplete_names_in_both_formats=Autocompletar_nomes_em_ambos_os_formatos @@ -931,7 +929,7 @@ exportFormat=exportFormat Output_file_missing=Arquivo_de_saída_não_encontrado. No_search_matches.=Sem_correspondências. The_output_option_depends_on_a_valid_input_option.=A_opção_padrão_depende_de_uma_opção_de_referência_válida. -Default_import_style_for_drag&drop_of_PDFs=Estilo_de_importação_padrão_para_Arrastar_e_Soltar_de_PDFs +Default_import_style_for_drag_and_drop_of_PDFs=Estilo_de_importação_padrão_para_Arrastar_e_Soltar_de_PDFs Default_PDF_file_link_action=Ação_de_link_de_arquivo_PDF_padrão Filename_format_pattern=Modelo_de_formato_de_nome_de_arquivo Additional_parameters=Parâmetros_adicionais @@ -1055,7 +1053,7 @@ Find_unlinked_files=Encontrar_arquivos_não_referenciados Unselect_all=Desmarcar_todas Expand_all=Expandir_todos Collapse_all=Reduzir_todos -Choose_Directory=Escolha_Diretório +Choose_directory=Escolha_Diretório Use_the_selected_directory_to_start_with_the_search.=Usar_o_diretório_selecionado_para_começar_a_busca Opens_the_file_browser.=Abrir_o_gerenciador_de_arquivos Scan_directory=Varrer_diretório @@ -1129,7 +1127,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=Se_estiver_cone Error_message\:=Mensagem_de_erro\: Created_group_"%0".=Grupo_criado_"%0". If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=Se_a_referência_colada_ou_importada_já_possuir_o_campo_definido,_sobrescrever. -Import_Metadata_From_PDF=Importar_Metadados_do_PDF +Import_metadata_from_PDF=Importar_Metadados_do_PDF Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Não_conectado_a_nenhum_documento_do_Writer._Por_favor_assegure-se_de_que_um_documento_está_aberto,_e_use_o_botão_'Selecionar_documento_do_Writer'_para_conectar_a_ele. Removed_all_subgroups_of_group_"%0".=Todos_os_subgrupos_do_grupo_"%0"_foram_removidos. To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Para_desabilitar_o_modo_memory_stick_renomeie_ou_remova_o_arquivo_jabref.xml_no_mesmo_diretório_que_o_JabRef @@ -1231,7 +1229,7 @@ Unmarked_selected_entry=Registro_selecionado_desmarcado Unmarked_all_entries=Todos_os_registros_desmarcados -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Não_foi_possivel_encontrar_o_Look_&_Feel_selecionado,_o_Look_&_Feel_padrão_sera_usado. +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Não_foi_possivel_encontrar_o_look_and_feel_selecionado,_o_look_and_feel_padrão_sera_usado. Could_not_open_browser.=Não_foi_possível_abrir_o_navegador. Opens_JabRef's_GitHub_page=Abrir_a_página_do_JabRef_no_GitHub @@ -1306,7 +1304,7 @@ OpenDocument_spreadsheet= OpenDocument_text= Please_move_the_file_manually_and_link_in_place.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Return_to_JabRef= @@ -1620,3 +1618,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 0a74a044f182..fc3284ee02d6 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1199,7 +1199,7 @@ Select_file_from_ZIP-archive=Выбрать_файл_из_ZIP-архива -Select_new_ImportFormat_Subclass=Выбрать_новый_подкласс_ImportFormat +Select_new_ImportFormat_subclass=Выбрать_новый_подкласс_ImportFormat Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Выбрать_узлы_дерева_для_просмотра_и_применения/отклонения_изменений Selected_entries=Записи_выбраны @@ -1215,7 +1215,6 @@ Set_table_font=Настройка_шрифта_таблицы Settings=Параметры -Setup_selectors=Параметры_выбора Shortcut=Ярлык @@ -1375,7 +1374,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Группа_содержит_записи,_в_которых_поле_%0_содержит_регулярное_выражение_%1_ This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Для_этой_операции_необходимо_определение_ключей_BibTeX_всех_выбранных_записей. -This_operation_requires_at_least_one_entry.=Для_этой_операции_необходима_по_крайней_мере_одна_запись. This_operation_requires_one_or_more_entries_to_be_selected.=Для_этой_операции_необходимо_выбрать_одну_или_несколько_записей. @@ -1651,8 +1649,8 @@ Create_blank_entry_linking_the_PDF=Создание_пустой_записи_с Only_attach_PDF=Приложить_только_PDF Title=Заглавие No_internet_connection.=Интернет-подключение_отсутствует. -Create_New_Entry=Создание_новой_записи -Update_Existing_Entry=Изменение_существующей_записи +Create_new_entry=Создание_новой_записи +Update_existing_entry=Изменение_существующей_записи Autocomplete_names_in_'Firstname_Lastname'_format_only=Автозавершение_имен_только_для_формата_'Имя_Фамилия' Autocomplete_names_in_'Lastname,_Firstname'_format_only=Автозавершение_имен_только_для_формата_'Фамилия,_Имя' Autocomplete_names_in_both_formats=Автозавершение_имен_в_обоих_форматах @@ -1673,7 +1671,7 @@ exportFormat=Формат_экспорта Output_file_missing=Отсутствует_файл_вывода No_search_matches.=Нет_совпадений_для_поиска. The_output_option_depends_on_a_valid_input_option.=Параметры_вывода_зависят_от_допустимых_параметров_ввода. -Default_import_style_for_drag&drop_of_PDFs=Стиль_импорта_по_умолчанию_для_режима_перетаскивания_PDF +Default_import_style_for_drag_and_drop_of_PDFs=Стиль_импорта_по_умолчанию_для_режима_перетаскивания_PDF Default_PDF_file_link_action=Действие_для_ссылки_на_файл_PDF_по_умолчанию Filename_format_pattern=Шаблон_формата_имени_файла Additional_parameters=Дополнительные_параметры @@ -1799,7 +1797,7 @@ Find_unlinked_files=Поиск_несвязанных_файлов Unselect_all=Отменить_выбор_всех Expand_all=Развернуть_все Collapse_all=Свернуть_все -Choose_Directory=Выбрать_каталог_файлов +Choose_directory=Выбрать_каталог_файлов Use_the_selected_directory_to_start_with_the_search.=Использовать_выбранный_каталог_файлов_для_начала_поиска. Opens_the_file_browser.=Открывает_окно_обзора_файлов. Scan_directory=Сканировать_каталог_файлов @@ -1873,7 +1871,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=При_подк Error_message\:=Сообщение_об_ошибке\: Created_group_"%0".=Создана_группа_"%0". If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=Перезаписать,_если_поле_для_вставленной_или_импортированной_записи_уже_задано. -Import_Metadata_From_PDF=Импорт_метаданных_из_PDF +Import_metadata_from_PDF=Импорт_метаданных_из_PDF Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Отсутствует_подключение_к_документу_Writer._Убедитесь,_что_документ_открыт_и_нажмите_кнопку_'Выбрать_документ_Writer'_для_подключения. Removed_all_subgroups_of_group_"%0".=Все_подгруппы_группы_"%0"_удалены. To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Для_отключения_режима_флеш-памяти_переименуйте_или_удалите_файл_jabref.xml_в_каталоге_JabRef. @@ -1979,7 +1977,7 @@ Toggle_print_status=Изменить_статус_'печать' Unmarked_all_entries=Отмена_отметки_всех_записей -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Не_удалось_найти_запрошенное_представление._Используется_представление_по_умолчанию. +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Не_удалось_найти_запрошенное_представление._Используется_представление_по_умолчанию. Opens_JabRef's_GitHub_page=Открывает_страницу_JabRef_на_GitHub Could_not_open_browser.=Не_удалось_открыть_браузер. @@ -2053,7 +2051,7 @@ OpenDocument_spreadsheet= OpenDocument_text= Please_move_the_file_manually_and_link_in_place.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Return_to_JabRef= @@ -2370,3 +2368,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 8f18ec74669e..cb76703aa2ff 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -167,7 +167,7 @@ Character_encoding_'%0'_is_not_supported.=Teckenkodningen_'%0'_stöds_inte. Characters_to_ignore=Bokstäver_att_ignorera Check_existing_file_links=Kontrollera_befintliga_fillänkar Check_links=Kontrollera_länkar -Choose_Directory=Välj_mapp +Choose_directory=Välj_mapp Choose_OpenOffice/LibreOffice_executable=Välj_OpenOffice/LibreOffice-program Choose_pattern=Välj_mönster Choose_the_URL_to_download.=Välj_URL_att_ladda_ned. @@ -266,7 +266,7 @@ Could_not_run_the_'vim'_program.=Kunde_inte_köra_'vim'. Could_not_run_the_gnuclient/emacsclient_program._Make_sure_you_have_the_emacsclient/gnuclient_program_installed_and_available_in_the_PATH.= Could_not_save,_file_locked_by_another_JabRef_instance.=Kunde_inte_spara._Filen_låst_av_en_annan_JabRef-instans. Could_not_save_file.=Kunde_inte_spara_fil. -Create_New_Entry=Skapa_ny_post +Create_new_entry=Skapa_ny_post Create_blank_entry_linking_the_PDF=Skapa_tom_post_som_länkar_till_PDF\:en Create_directory_based_keywords=Skapa_nyckelord_baserade_på_mapp Create_entry_based_on_XMP_data=Skapa_post_baserat_på_XMP-data @@ -296,7 +296,7 @@ Default_PDF_file_link_action=Standardhändelse_för_PDF-fil Default_bibliography_mode=Standardläge_för_databas Default_encoding=Standardteckenkodning Default_grouping_field=Standardfält_för_gruppering -Default_import_style_for_drag&drop_of_PDFs= +Default_import_style_for_drag_and_drop_of_PDFs= Default_look_and_feel=Standard-'look-and-feel' Default_pattern=Standardmönster Default_sort_criteria=Standardsortering @@ -571,7 +571,7 @@ Ill-formed_entrytype_comment_in_bib_file= Immediate_subgroups= Import=Importera ImportFormat_class= -Import_Metadata_From_PDF=Importera_metadata_från_PDF +Import_metadata_from_PDF=Importera_metadata_från_PDF Import_and_keep_old_entry=Importera_och_behåll_gammal_post Import_and_remove_old_entry=Importera_och_ta_bort_gammal_post Import_canceled_by_user=Import_avbröts_av_användare @@ -901,7 +901,7 @@ Raw_source=Rå_källkod Read_status=Lässtatus Read_status_read=Läst Read_status_skimmed=Skummat -Really_delete_the_selected_%0_entries?=Verkligen_ta_bort_de_%0_valda_posterna? +Really_delete_the_%0_selected_entries?=Verkligen_ta_bort_de_%0_valda_posterna? Really_delete_the_selected_entry?=Verkligen_ta_bort_den_valda_posten? Rearrange_tabs_alphabetically_by_title=Sortera_flikar_i_alfabetisk_ordning Rebind_C-a,_too= @@ -1038,7 +1038,7 @@ Select_external_application=Välj_program Select_file_from_ZIP-archive=Välj_fil_från_Zip-arkiv Select_file_type\:=Välj_filtyp\: Select_files=Välj_filer -Select_new_ImportFormat_Subclass= +Select_new_ImportFormat_subclass= Select_one_entry.=Välj_en_post. Select_style=Välj_stil Select_target_SQL_database\:= @@ -1064,7 +1064,6 @@ Set_table_font=Sätt_tabelltypsnitt Setting_all_preferences_to_default_values.=Återställer_alla_inställningar_till_standardvärden Settings=Alternativ Settings_for_%0=Alternativ_för_%0 -Setup_selectors= Shortcut=Genväg Show/edit_BibTeX_source=Visa/ändra_BibTeX-källkod Show_'Firstname_Lastname'=Visa_som_'Förnamn_Efternamn' @@ -1189,7 +1188,6 @@ This_group_contains_entries_whose_%0_field_contains_the_regular_expressio This_is_a_simple_copy_and_paste_dialog._First_load_or_paste_some_text_into_the_text_input_area.
    After_that,_you_can_mark_text_and_assign_it_to_a_BibTeX_field.= This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.= This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Denna_operationen_kräver_att_alla_valda_poster_har_en_BibTeX-nyckel. -This_operation_requires_at_least_one_entry.=Denna_operationen_kräver_minst_en_post. This_operation_requires_one_or_more_entries_to_be_selected.=Den_här_operationen_kräver_att_en_eller_flera_poster_är_valda. This_search_contains_entries_in_which=Denna_sökning_innehåller_poster_där This_search_contains_entries_in_which_any_field_contains_the_regular_expression_%0=Denna_sökning_innehåller_poster_där_något_fält_innehåller_det_reguljära_uttrycket_%0 @@ -1217,7 +1215,7 @@ Unable_to_clear_preferences.=Kan_inte_rensa_inställningar. Unable_to_connect._One_possible_reason_is_that_JabRef_and_OpenOffice/LibreOffice_are_not_both_running_in_either_32_bit_mode_or_64_bit_mode.= Unable_to_connect_to_FreeCite_online_service.= Unable_to_create_backup=Kan_inte_skapa_säkerhetskopia -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.= Unable_to_open_file.=Kan_inte_öppna_fil. Unable_to_open_link.=Kan_inte_öppna_länk. Unable_to_open_link._The_application_'%0'_associated_with_the_file_type_'%1'_could_not_be_called.= @@ -1242,7 +1240,7 @@ Unmarked_selected_entry=Avmarkera_valda_poster Unselect_all= Unsupported_version_of_class_%0\:_%1= Up=Uppåt -Update_Existing_Entry=Uppdatera_befintlig_post +Update_existing_entry=Uppdatera_befintlig_post Update_keywords=Uppdatera_nyckelord Update_timestamp_on_modification=Uppdatera_tidsstämpeln_efter_ändring Update_to_current_column_order= @@ -1563,3 +1561,4 @@ Please_open_%0_manually.=Öppna_%0_för_hand. The_link_has_been_copied_to_the_clipboard.=Länken_har_kopierats_till_urklipp. Online_help_forum=Onlineforum +Custom=Egna diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index ad379f6ffc13..56ebc0dcf1d4 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -625,7 +625,7 @@ Select_encoding=Kodlamayı_seç Select_entry_type=Girdi_türünü_seç Select_external_application=Harici_uygulamayı_seç Select_file_from_ZIP-archive=ZIP_arşivinden_dosyayı_seçiniz -Select_new_ImportFormat_Subclass=Yeni_İçe_Aktarım_Biçemi_Altsınıfını_seçiniz +Select_new_ImportFormat_subclass=Yeni_İçe_Aktarım_Biçemi_Altsınıfını_seçiniz Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Değişiklikleri_görmek_ve_kabul_ya_da_reddetmek_için_ağaç_düğümlerini_seçiniz Selected_entries=Seçili_girdiler Server_hostname=Sunucu_Makine_adı @@ -636,7 +636,6 @@ Set_general_fields=Genel_alanları_ata Set_main_external_file_directory=Ana_harici_dosya_dizinini_ayarla Set_table_font=Tablo_yazıtipini_ayarla Settings=Ayarlar -Setup_selectors=Kurma_seçicileri Shortcut=Kısayol Show/edit_BibTeX_source=BibTeX_kaynağın_göster/düzenle Show_'Firstname_Lastname'='Ad_Soyad'_göster @@ -715,7 +714,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=Bu_grup,_%0_alanı_%1_düzenli_ifadesini_içeren_girdileri_içerir This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Bu,_JabRef'in_her_dosya_linki_bulup_dosyanın_var_olup_olmadığını_kontrol_etmesini_sağlar._Eğer_yoksa,_sorunu
    çözmek_için_seçenekler_sunulacaktır. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Bu_işlem,_tüm_seçili_girdilerin_tanımlı_BibTeX_anahtarlarının_olmasını_gerektirir. -This_operation_requires_at_least_one_entry.=Bu_işlem_en_az_bir_girdi_gerektirir. This_operation_requires_one_or_more_entries_to_be_selected.=Bu_işlem,_bir_ya_da_daha_çok_girdinin_seçili_olmasını_gerektirir. Toggle_abbreviation=Kısaltmayı_aç/kapat Toggle_entry_preview=Girdi_önizlemeyi_aç/kapat @@ -929,8 +927,8 @@ Create_blank_entry_linking_the_PDF=PDF'yle_bağlantılı_olarak_boş_girdi_oluş Only_attach_PDF=Yalnızca_PDF'yi_ekle Title=Başlık No_internet_connection.=Internet_Bağlantısı_Yok. -Create_New_Entry=Yeni_Girdi_Oluştur -Update_Existing_Entry=Mevcut_Girdiyi_Güncelle +Create_new_entry=Yeni_Girdi_Oluştur +Update_existing_entry=Mevcut_Girdiyi_Güncelle Autocomplete_names_in_'Firstname_Lastname'_format_only=İsimleri_yalnızca_'Ad_Soyad'_biçiminde_otomatik_tamamla Autocomplete_names_in_'Lastname,_Firstname'_format_only=İsimleri_yalnızca_'Soyad,_Ad'_biçiminde_otomatik_tamamla Autocomplete_names_in_both_formats=İsimleri_her_iki_biçimde_otomatik_tamamla @@ -951,7 +949,7 @@ exportFormat=dışa-aktarımBiçimi Output_file_missing=Çıktı_dosyası_kayıp No_search_matches.=Eşleşen_arama_yok The_output_option_depends_on_a_valid_input_option.=Çıktı_seçeneği_geçerli_bir_girdi_seçeneğine_bağlmlıdır. -Default_import_style_for_drag&drop_of_PDFs=Sürüklenip_bırakılan_PDF'lerin_öntanımlı_içe_aktarım_stili +Default_import_style_for_drag_and_drop_of_PDFs=Sürüklenip_bırakılan_PDF'lerin_öntanımlı_içe_aktarım_stili Default_PDF_file_link_action=Öntanımlı_PDF_dosyası_bağlantı_eylemi Filename_format_pattern=Dosya_adı_biçimi_deseni Additional_parameters=Ek_parametreler @@ -1075,7 +1073,7 @@ Find_unlinked_files=Bağlantısız_dosyaları_bul Unselect_all=Tüm_seçimleri_kaldır Expand_all=Tümünü_genişlet Collapse_all=Tüm_genişletmeyi_kaldır -Choose_Directory=Dizin_Seç +Choose_directory=Dizin_Seç Use_the_selected_directory_to_start_with_the_search.=Aramayı_başlatmak_için_seçili_dizini_kullan. Opens_the_file_browser.=Dosya_göz_atıcısını_başlatır. Scan_directory=Dizini_tara @@ -1150,7 +1148,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.=Manuel_bağlan Error_message\:=Hata_mesajı\: Created_group_"%0".=Grup_"%0"_oluşturuldu. If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.=Eğer_yapıştırılmış_ya_da_içe_aktarılmış_bir_girdi_alanı_atadıysa_üzerine_yaz. -Import_Metadata_From_PDF=Metadata'yı_PDF'ten_İçe_Aktar +Import_metadata_from_PDF=Metadata'yı_PDF'ten_İçe_Aktar Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.=Herhangi_bir_Writer_belgesine_bağlanılmadı._Lütfen_bir_belgenin_açık_olduğuna_emin_olun_ve_ona_bağlanmak_için_"Write_belgesini_seç"_düğmesini_kullanın. Removed_all_subgroups_of_group_"%0".=Grup_"%0"'ın_bütün_alt_grupları_silindi. To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.=Taşınabilir_hafıza_kartı_kipini_etkisizleştirmek_için_JabRef'le_aynı_klasördeki_jabref.xml_dosyasını_silin_ya_da_adını_değiştirin. @@ -1251,7 +1249,7 @@ Unmarked_selected_entry=Seçilmiş_girdinin_işareti_kaldırıldı Unmarked_all_entries=Tüm_girdilerin_işareti_kaldırıldı -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=Arzu_edilen_Görünüm_ve_Tema_bulunamadığından_öntanımlı_olan_kullanıldı. +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=Arzu_edilen_Görünüm_ve_Tema_bulunamadığından_öntanımlı_olan_kullanıldı. Could_not_open_browser.=Tarayıcı_açılamadı. Opens_JabRef's_GitHub_page=JabRef'in_GitHub_sayfasını_açar @@ -1326,7 +1324,7 @@ OpenDocument_spreadsheet=AçıkBelge_iş_tablosu OpenDocument_text=AçıkBelge_metni Please_move_the_file_manually_and_link_in_place.=Lütfen_dosyayı_elle_taşıyın_ve_yerinde_bağlantı_kurun. Print_entry_preview=Girdi_yazdırma_önizleme -Really_delete_the_selected_%0_entries?=Gerçekten_seçili_%0_girdi_silinsin_mi? +Really_delete_the_%0_selected_entries?=Gerçekten_seçili_%0_girdi_silinsin_mi? Really_delete_the_selected_entry?=Gerçekten_seçili_girdi_silinsin_mi? Removed_all_groups=Tüm_gruplar_silindi Replace_original_entry=Orjinal_girdinin_yerine_koy @@ -1639,3 +1637,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 3fc4d0073ca3..751b5df259b3 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1227,7 +1227,7 @@ Select_file_from_ZIP-archive=Chọn_tập_tin_từ_tập_tin_Zip -Select_new_ImportFormat_Subclass=Chọn_Lớp.phụ_Định.dạng.nhập_mới +Select_new_ImportFormat_subclass=Chọn_Lớp.phụ_Định.dạng.nhập_mới Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Chọn_các_nốt_trên_sơ_đồ_hình_cây_để_xem_và_chấp_nhận_hoặc_từ_chối_thay_đổi Selected_entries=Các_mục_được_chọn @@ -1243,7 +1243,6 @@ Set_table_font=Chọn_bảng_phông_chữ Settings=Các_thiết_lập -Setup_selectors=Cài_đặt_các_trình_chọn Shortcut=Phím_tắt @@ -1406,7 +1405,6 @@ This_group_contains_entries_whose_%0_field_contains_the_regular_expressio This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=Điều_này_khiến_cho_JabRef_tìm_từng_liên_kết_trong_tổng_số_tập_tin_và_kiểm_tra_xem_tập_tin_có_tồn_tại_không._Nếu_không_bạn_sẽ_được_cung_cấp_các_tùy_chọn
    để_giải_quyết_trục_trặc. This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=Lệnh_này_yêu_cầu_tất_cả_các_mục_được_chọn_phải_có_khóa_BibTeX. -This_operation_requires_at_least_one_entry.=Lệnh_này_yêu_cầu_phải_có_ít_nhất_một_mục. This_operation_requires_one_or_more_entries_to_be_selected.=Lệnh_này_yêu_cầu_phải_chọn_trước_một_hoặc_nhiều_mục. @@ -1682,8 +1680,8 @@ Create_blank_entry_linking_the_PDF= Only_attach_PDF= Title= No_internet_connection.= -Create_New_Entry= -Update_Existing_Entry= +Create_new_entry= +Update_existing_entry= Autocomplete_names_in_'Firstname_Lastname'_format_only= Autocomplete_names_in_'Lastname,_Firstname'_format_only= Autocomplete_names_in_both_formats= @@ -1704,7 +1702,7 @@ exportFormat= Output_file_missing= No_search_matches.= The_output_option_depends_on_a_valid_input_option.= -Default_import_style_for_drag&drop_of_PDFs= +Default_import_style_for_drag_and_drop_of_PDFs= Default_PDF_file_link_action= Filename_format_pattern= Cite_selected_entries_between_parenthesis= @@ -1829,7 +1827,7 @@ Find_unlinked_files= Unselect_all= Expand_all= Collapse_all= -Choose_Directory= +Choose_directory= Use_the_selected_directory_to_start_with_the_search.= Opens_the_file_browser.= Scan_directory= @@ -1901,7 +1899,7 @@ If_connecting_manually,_please_verify_program_and_library_paths.= Error_message\:= Created_group_"%0".= If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.= -Import_Metadata_From_PDF= +Import_metadata_from_PDF= Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.= To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.= Use_the_following_delimiter_character(s)\:= @@ -2001,7 +1999,7 @@ Unmarked_selected_entry= Unmarked_all_entries= -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.= +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.= Could_not_open_browser.= Opens_JabRef's_GitHub_page= @@ -2078,7 +2076,7 @@ OpenDocument_text= Opening_dialog= Please_move_the_file_manually_and_link_in_place.= Print_entry_preview= -Really_delete_the_selected_%0_entries?= +Really_delete_the_%0_selected_entries?= Really_delete_the_selected_entry?= Removed_all_groups= Removed_all_subgroups_of_group_"%0".= @@ -2394,3 +2392,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index a1357497fb60..d9578dbbe2b8 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -638,7 +638,7 @@ Select_encoding=选择编码 Select_entry_type=选择记录类型 Select_external_application=选择外部程序 Select_file_from_ZIP-archive=从_ZIP-压缩包中选择文件 -Select_new_ImportFormat_Subclass=选择新的_ImportFormat_子类 +Select_new_ImportFormat_subclass=选择新的_ImportFormat_子类 Select_the_tree_nodes_to_view_and_accept_or_reject_changes=选择树节点查看和接受/拒绝修改 Selected_entries=选中的记录 Server_hostname=服务器主机 @@ -649,7 +649,6 @@ Set_general_fields=设置_general_域 Set_main_external_file_directory=设置外部文件的主目录 Set_table_font=设置表格字体 Settings=设置 -Setup_selectors=设置下拉菜单项 Shortcut=快捷键 Show/edit_BibTeX_source=显示/编辑_BibTeX_源代码 Show_'Firstname_Lastname'=显示_'名_(Firstname)_姓_(Lastname)' @@ -734,7 +733,6 @@ This_group_contains_entries_whose_%0_field_contains_the_keyword_%1 This_group_contains_entries_whose_%0_field_contains_the_regular_expression_%1=此分组中记录的_%0_域包含正则表达式_%1_ This_makes_JabRef_look_up_each_file_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options
    to_resolve_the_problem.=该选项使_JabRef_遍历所有文件链接,检查链接文件是否存在。如果不存在,您将会得到一个选项来处理这个问题。 This_operation_requires_all_selected_entries_to_have_BibTeX_keys_defined.=此操作要求所有选中记录的_BibTeX_键值不为空。 -This_operation_requires_at_least_one_entry.=此操作要求至少选中一个记录。 This_operation_requires_one_or_more_entries_to_be_selected.=这个操作要求选中一条或多条记录。 This_search_contains_entries_in_which=这次搜索的结果记录符合条件: This_search_contains_entries_in_which_any_field_contains_the_regular_expression_%0=这次搜索的结果记录符合条件:记录的任意域包含正则表达式_%0 @@ -984,8 +982,8 @@ Create_blank_entry_linking_the_PDF=为_PDF_新建一条空白记录 Only_attach_PDF=只附加_PDF_到记录 Title=标题 No_internet_connection.=无法连接到互联网。 -Create_New_Entry=创建新记录 -Update_Existing_Entry=更新已有记录 +Create_new_entry=创建新记录 +Update_existing_entry=更新已有记录 Autocomplete_names_in_'Firstname_Lastname'_format_only=仅自动补全形如_'Firstname_Lastname'_格式的姓名 Autocomplete_names_in_'Lastname,_Firstname'_format_only=仅自动补全形如_'Lastname,_Firstname'_格式的姓名 Autocomplete_names_in_both_formats=自动补全两种格式的姓名 @@ -1006,7 +1004,7 @@ exportFormat=导出格式 Output_file_missing=没有输出文件 No_search_matches.=没有匹配的搜索结果 The_output_option_depends_on_a_valid_input_option.=输出选项依赖于合法的输入选项。 -Default_import_style_for_drag&drop_of_PDFs=拖入_PDF_的默认导入策略 +Default_import_style_for_drag_and_drop_of_PDFs=拖入_PDF_的默认导入策略 Default_PDF_file_link_action=默认_PDF_文件链接操作 Filename_format_pattern=文件名格式化表达式 Additional_parameters=额外的参数 @@ -1132,7 +1130,7 @@ Find_unlinked_files= Unselect_all= Expand_all= Collapse_all= -Choose_Directory=选择目录 +Choose_directory=选择目录 Use_the_selected_directory_to_start_with_the_search.= Opens_the_file_browser.= Scan_directory=扫描目录 @@ -1206,7 +1204,7 @@ Error_message\:= Created_group_"%0".= If_a_pasted_or_imported_entry_already_has_the_field_set,_overwrite.= -Import_Metadata_From_PDF= +Import_metadata_from_PDF= Not_connected_to_any_Writer_document._Please_make_sure_a_document_is_open,_and_use_the_'Select_Writer_document'_button_to_connect_to_it.= Removed_all_subgroups_of_group_"%0".= To_disable_the_memory_stick_mode_rename_or_remove_the_jabref.xml_file_in_the_same_folder_as_JabRef.= @@ -1308,7 +1306,7 @@ Unmarked_selected_entry=已取消标记选中的记录 Unmarked_all_entries=已取消标记所有记录 -Unable_to_find_the_requested_Look_&_Feel_and_thus_the_default_one_is_used.=无法找到要求的显示效果类,使用默认显示效果。 +Unable_to_find_the_requested_look_and_feel_and_thus_the_default_one_is_used.=无法找到要求的显示效果类,使用默认显示效果。 Could_not_open_browser.=无法打开浏览器。 Opens_JabRef's_GitHub_page=打开_JabRef_在_GitHub_上的页面 @@ -1384,7 +1382,7 @@ OpenDocument_spreadsheet=OpenDocument_spreadsheet OpenDocument_text=OpenDocument_text Please_move_the_file_manually_and_link_in_place.= Print_entry_preview=打印记录预览 -Really_delete_the_selected_%0_entries?=确定删除选中的_%0_条记录? +Really_delete_the_%0_selected_entries?=确定删除选中的_%0_条记录? Really_delete_the_selected_entry?=确定删除选中的记录? Removed_all_groups=已移除所有分组 Return_to_JabRef=返回_JabRef @@ -1633,3 +1631,5 @@ Please_open_%0_manually.= The_link_has_been_copied_to_the_clipboard.= Online_help_forum= + +Custom= From 06943e2b2bc4cf84b2b344fc1e24e2d4091ee743 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 16:06:43 +0200 Subject: [PATCH 199/268] Encapsulated some fields in Globals (#1571) --- src/main/java/net/sf/jabref/Globals.java | 36 +++++++++++++++---- .../net/sf/jabref/collab/ChangeScanner.java | 4 +-- .../jabref/exporter/SaveDatabaseAction.java | 6 ++-- .../java/net/sf/jabref/gui/BasePanel.java | 10 +++--- .../java/net/sf/jabref/gui/JabRefFrame.java | 17 ++++----- .../jabref/gui/entryeditor/EntryEditor.java | 4 +-- .../sf/jabref/gui/fieldeditors/TextArea.java | 2 +- .../sf/jabref/gui/fieldeditors/TextField.java | 2 +- .../sf/jabref/gui/maintable/MainTable.java | 2 +- .../net/sf/jabref/gui/search/SearchBar.java | 2 +- 10 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/main/java/net/sf/jabref/Globals.java b/src/main/java/net/sf/jabref/Globals.java index bd77eec76ed0..6e8577b5ed1d 100644 --- a/src/main/java/net/sf/jabref/Globals.java +++ b/src/main/java/net/sf/jabref/Globals.java @@ -15,6 +15,8 @@ */ package net.sf.jabref; +import java.util.Optional; + import net.sf.jabref.collab.FileUpdateMonitor; import net.sf.jabref.exporter.AutoSaveManager; import net.sf.jabref.gui.GlobalFocusListener; @@ -64,8 +66,18 @@ public class Globals { */ public static JournalAbbreviationLoader journalAbbreviationLoader; + // Key binding preferences private static KeyBindingPreferences keyPrefs; + // Background tasks + private static GlobalFocusListener focusListener; + private static FileUpdateMonitor fileUpdateMonitor; + private static StreamEavesdropper streamEavesdropper; + + // Autosave manager + private static AutoSaveManager autoSaveManager; + + // Key binding preferences public static KeyBindingPreferences getKeyPrefs() { if (keyPrefs == null) { keyPrefs = new KeyBindingPreferences(prefs); @@ -75,23 +87,29 @@ public static KeyBindingPreferences getKeyPrefs() { // Background tasks - public static GlobalFocusListener focusListener; - public static FileUpdateMonitor fileUpdateMonitor; - public static StreamEavesdropper streamEavesdropper; - public static void startBackgroundTasks() { Globals.focusListener = new GlobalFocusListener(); Globals.streamEavesdropper = StreamEavesdropper.eavesdropOnSystem(); Globals.fileUpdateMonitor = new FileUpdateMonitor(); - JabRefExecutorService.INSTANCE.executeWithLowPriorityInOwnThread(Globals.fileUpdateMonitor, "FileUpdateMonitor"); + JabRefExecutorService.INSTANCE.executeWithLowPriorityInOwnThread(Globals.fileUpdateMonitor, + "FileUpdateMonitor"); + } + + public static GlobalFocusListener getFocusListener() { + return focusListener; } + public static FileUpdateMonitor getFileUpdateMonitor() { + return fileUpdateMonitor; + } - // Autosave manager - public static AutoSaveManager autoSaveManager; + public static StreamEavesdropper getStreamEavesdropper() { + return streamEavesdropper; + } + // Autosave manager public static void startAutoSaveManager(JabRefFrame frame) { Globals.autoSaveManager = new AutoSaveManager(frame); Globals.autoSaveManager.startAutoSaveTimer(); @@ -105,4 +123,8 @@ public static void stopAutoSaveManager() { Globals.autoSaveManager = null; } } + + public static Optional getAutoSaveManager() { + return Optional.ofNullable(Globals.autoSaveManager); + } } diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index 1f632e4b7d87..c37ce2732b7b 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -95,7 +95,7 @@ public void run() { try { // Parse the temporary file. - File tempFile = Globals.fileUpdateMonitor.getTempFile(panel.fileMonitorHandle()); + File tempFile = Globals.getFileUpdateMonitor().getTempFile(panel.fileMonitorHandle()); ParserResult pr = OpenDatabaseAction.loadDatabase(tempFile, Globals.prefs.getDefaultEncoding()); inTemp = pr.getDatabase(); mdInTemp = pr.getMetaData(); @@ -166,7 +166,7 @@ private void storeTempDatabase() { .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); SaveSession ss = databaseWriter.saveDatabase(new BibDatabaseContext(inTemp, mdInTemp, defaults), prefs); - ss.commit(Globals.fileUpdateMonitor.getTempFile(panel.fileMonitorHandle())); + ss.commit(Globals.getFileUpdateMonitor().getTempFile(panel.fileMonitorHandle())); } catch (SaveException ex) { LOGGER.warn("Problem updating tmp file after accepting external changes", ex); } diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java index 2d1105031f00..d43042c583a7 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java @@ -132,7 +132,7 @@ public void run() { success = saveDatabase(panel.getBibDatabaseContext().getDatabaseFile(), false, panel.getBibDatabaseContext().getMetaData().getEncoding()); - Globals.fileUpdateMonitor.updateTimeStamp(panel.getFileMonitorHandle()); + Globals.getFileUpdateMonitor().updateTimeStamp(panel.getFileMonitorHandle()); } else { // No file lock success = false; @@ -331,7 +331,7 @@ public void saveAs() throws Throwable { } // Register so we get notifications about outside changes to the file. try { - panel.setFileMonitorHandle(Globals.fileUpdateMonitor.addUpdateListener(panel, + panel.setFileMonitorHandle(Globals.getFileUpdateMonitor().addUpdateListener(panel, panel.getBibDatabaseContext().getDatabaseFile())); } catch (IOException ex) { LOGGER.error("Problem registering file change notifications", ex); @@ -368,7 +368,7 @@ public boolean isCanceled() { */ private boolean checkExternalModification() { // Check for external modifications: - if (panel.isUpdatedExternally() || Globals.fileUpdateMonitor.hasBeenModified(panel.getFileMonitorHandle())) { + if (panel.isUpdatedExternally() || Globals.getFileUpdateMonitor().hasBeenModified(panel.getFileMonitorHandle())) { String[] opts = new String[] {Localization.lang("Review changes"), Localization.lang("Save"), Localization.lang("Cancel")}; int answer = JOptionPane.showOptionDialog(panel.frame(), diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 44346461cc38..6bb4d65094f0 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -253,7 +253,7 @@ public BasePanel(JabRefFrame frame, BibDatabaseContext bibDatabaseContext) { } else { // Register so we get notifications about outside changes to the file. try { - fileMonitorHandle = Globals.fileUpdateMonitor.addUpdateListener(this, file); + fileMonitorHandle = Globals.getFileUpdateMonitor().addUpdateListener(this, file); } catch (IOException ex) { LOGGER.warn("Could not register FileUpdateMonitor", ex); } @@ -2030,7 +2030,7 @@ private class UndoAction implements BaseAction { @Override public void action() { try { - JComponent focused = Globals.focusListener.getFocused(); + JComponent focused = Globals.getFocusListener().getFocused(); if ((focused != null) && (focused instanceof FieldEditor) && focused.hasFocus()) { // User is currently editing a field: // Check if it is the preamble: @@ -2118,7 +2118,7 @@ private class RedoAction implements BaseAction { public void action() { try { - JComponent focused = Globals.focusListener.getFocused(); + JComponent focused = Globals.getFocusListener().getFocused(); if ((focused != null) && (focused instanceof FieldEditor) && focused.hasFocus()) { // User is currently editing a field: storeCurrentEdit(); @@ -2175,7 +2175,7 @@ public void fileUpdated() { // The file is locked even after the maximum wait. Do nothing. LOGGER.error("File updated externally, but change scan failed because the file is locked."); // Perturb the stored timestamp so successive checks are made: - Globals.fileUpdateMonitor.perturbTimestamp(getFileMonitorHandle()); + Globals.getFileUpdateMonitor().perturbTimestamp(getFileMonitorHandle()); return; } @@ -2215,7 +2215,7 @@ public void fileRemoved() { */ public void cleanUp() { if (fileMonitorHandle != null) { - Globals.fileUpdateMonitor.removeUpdateListener(fileMonitorHandle); + Globals.getFileUpdateMonitor().removeUpdateListener(fileMonitorHandle); } // Check if there is a FileUpdatePanel for this BasePanel being shown. If so, // remove it: diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 77082a8976ba..0a6cd4addefa 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -416,7 +416,7 @@ public void actionPerformed(ActionEvent e) { private final AbstractAction manageJournals = new ManageJournalsAction(this); private final AbstractAction databaseProperties = new DatabasePropertiesAction(); private final AbstractAction bibtexKeyPattern = new BibtexKeyPatternAction(); - private final AbstractAction errorConsole = new ErrorConsoleAction(this, Globals.streamEavesdropper, GuiAppender.CACHE); + private final AbstractAction errorConsole = new ErrorConsoleAction(this, Globals.getStreamEavesdropper(), GuiAppender.CACHE); private final AbstractAction dbConnect = new GeneralAction(Actions.DB_CONNECT, Localization.menuTitle("Connect to external SQL database"), @@ -633,7 +633,7 @@ public void windowClosing(WindowEvent e) { groupToggle.setSelected(sidePaneManager.isComponentVisible("groups")); previewToggle.setSelected(Globals.prefs.getBoolean(JabRefPreferences.PREVIEW_ENABLED)); fetcherToggle.setSelected(sidePaneManager.isComponentVisible(generalFetcher.getTitle())); - Globals.focusListener.setFocused(bp.getMainTable()); + Globals.getFocusListener().setFocused(bp.getMainTable()); setWindowTitle(); editModeAction.initName(); // Update search autocompleter with information for the correct database: @@ -781,9 +781,8 @@ private void tearDownJabRef(List filenames) { CustomEntryTypesManager.saveCustomEntryTypes(prefs); // Clear autosave files: - if (Globals.autoSaveManager != null) { - Globals.autoSaveManager.clearAutoSaves(); - } + // TODO: Is this really needed since clearAutoSave() is called in stopAutoSaveManager() a few rows below? + Globals.getAutoSaveManager().ifPresent(manager -> manager.clearAutoSaves()); prefs.flush(); @@ -793,9 +792,7 @@ private void tearDownJabRef(List filenames) { } // shutdown any timers that are may be active - if (Globals.autoSaveManager != null) { - Globals.stopAutoSaveManager(); - } + Globals.stopAutoSaveManager(); } /** @@ -1870,8 +1867,8 @@ public EditAction(String command, String menuTitle, String description, KeyStrok @Override public void actionPerformed(ActionEvent e) { - LOGGER.debug(Globals.focusListener.getFocused().toString()); - JComponent source = Globals.focusListener.getFocused(); + LOGGER.debug(Globals.getFocusListener().getFocused().toString()); + JComponent source = Globals.getFocusListener().getFocused(); Action action = source.getActionMap().get(command); if (action != null) { action.actionPerformed(new ActionEvent(source, 0, command)); diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 9b528f1f90ff..5716a75360f3 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -542,7 +542,7 @@ private void setupSourcePanel() { source.setTabSize(Globals.prefs.getInt(JabRefPreferences.INDENT)); source.addFocusListener(new FieldEditorFocusListener()); // Add the global focus listener, so a menu item can see if this field was focused when an action was called. - source.addFocusListener(Globals.focusListener); + source.addFocusListener(Globals.getFocusListener()); source.setFont(new Font("Monospaced", Font.PLAIN, Globals.prefs.getInt(JabRefPreferences.FONT_SIZE))); setupJTextComponent(source); updateSource(); @@ -693,7 +693,7 @@ private void scrollTo(int row) { * Makes sure the current edit is stored. */ public void storeCurrentEdit() { - Component comp = Globals.focusListener.getFocused(); + Component comp = Globals.getFocusListener().getFocused(); if (Objects.equals(comp, source) || ((comp instanceof FieldEditor) && this.isAncestorOf(comp))) { if (comp instanceof FieldEditor) { ((FieldEditor) comp).clearAutoCompleteSuggestion(); diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java b/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java index ef4ca0e9bd7e..c22f6c7c410a 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java @@ -52,7 +52,7 @@ public TextArea(String fieldName, String content) { // Add the global focus listener, so a menu item can see if this field // was focused when an action was called. - addFocusListener(Globals.focusListener); + addFocusListener(Globals.getFocusListener()); addFocusListener(new FieldEditorFocusListener()); scrollPane = new JScrollPane(this, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java b/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java index cc88ee6b0510..b93f474a7a37 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java @@ -58,7 +58,7 @@ public TextField(String fieldName, String content, boolean changeColorOnFocus) { // Add the global focus listener, so a menu item can see if this field // was focused when // an action was called. - addFocusListener(Globals.focusListener); + addFocusListener(Globals.getFocusListener()); if (changeColorOnFocus) { addFocusListener(new FieldEditorFocusListener()); } diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java index 3aef6ffc7ddc..be69f02a1867 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java @@ -127,7 +127,7 @@ public MainTable(MainTableFormat tableFormat, MainTableDataModel model, JabRefFr super(); this.model = model; - addFocusListener(Globals.focusListener); + addFocusListener(Globals.getFocusListener()); setAutoResizeMode(Globals.prefs.getInt(JabRefPreferences.AUTO_RESIZE_MODE)); this.tableFormat = tableFormat; diff --git a/src/main/java/net/sf/jabref/gui/search/SearchBar.java b/src/main/java/net/sf/jabref/gui/search/SearchBar.java index 11aa5ae42508..6492b8507ef0 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchBar.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchBar.java @@ -233,7 +233,7 @@ public void keyReleased(KeyEvent e) { autoCompleteSupport.install(); // Add the global focus listener, so a menu item can see if this field was focused when an action was called. - searchField.addFocusListener(Globals.focusListener); + searchField.addFocusListener(Globals.getFocusListener()); // Search if user press enter searchField.addActionListener(e -> performSearch()); From 25bbd0bfff4803bd324d195fffebc53b2819cf85 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 16:13:33 +0200 Subject: [PATCH 200/268] A few conversions of getField to getFieldOptional (#1548) * A few conversions of getField to getFieldOptional * Honoured comments and improved the cleanup * Removed Optional argument * Final comment fix * Removed fully specified qualifier --- .../net/sf/jabref/external/AutoSetLinks.java | 26 +++++------ .../jabref/external/SynchronizeFileField.java | 41 ++++++++--------- .../net/sf/jabref/logic/fulltext/ACS.java | 2 +- .../net/sf/jabref/logic/fulltext/ArXiv.java | 8 ++-- .../jabref/logic/fulltext/DoiResolution.java | 2 +- .../jabref/logic/fulltext/FindFullText.java | 4 +- .../jabref/logic/fulltext/GoogleScholar.java | 2 +- .../net/sf/jabref/logic/fulltext/IEEE.java | 7 +-- .../jabref/logic/fulltext/ScienceDirect.java | 2 +- .../jabref/logic/fulltext/SpringerLink.java | 2 +- .../net/sf/jabref/model/DuplicateCheck.java | 44 ++++++++++--------- .../sf/jabref/model/database/BibDatabase.java | 14 ++++-- .../net/sf/jabref/model/entry/BibEntry.java | 2 +- .../net/sf/jabref/model/entry/EntryUtil.java | 8 ++++ .../specialfields/SpecialFieldsUtils.java | 15 ++++--- .../sf/jabref/model/entry/EntryUtilTest.java | 9 +++- 16 files changed, 104 insertions(+), 84 deletions(-) diff --git a/src/main/java/net/sf/jabref/external/AutoSetLinks.java b/src/main/java/net/sf/jabref/external/AutoSetLinks.java index 3a9ee072be72..bc57847d50ea 100644 --- a/src/main/java/net/sf/jabref/external/AutoSetLinks.java +++ b/src/main/java/net/sf/jabref/external/AutoSetLinks.java @@ -78,26 +78,26 @@ public static Runnable autoSetLinks(final Collection entries, final Na diag.setTitle(Localization.lang("Automatically setting file links")); diag.getContentPane().add(prog, BorderLayout.CENTER); diag.getContentPane().add(label, BorderLayout.SOUTH); - + diag.pack(); diag.setLocationRelativeTo(diag.getParent()); } - + Runnable r = new Runnable() { - + @Override public void run() { // determine directories to search in List dirs = new ArrayList<>(); List dirsS = databaseContext.getFileDirectory(); dirs.addAll(dirsS.stream().map(File::new).collect(Collectors.toList())); - + // determine extensions Collection extensions = new ArrayList<>(); for (final ExternalFileType type : types) { extensions.add(type.getExtension()); } - + // Run the search operation: Map> result; if (Globals.prefs.getBoolean(JabRefPreferences.AUTOLINK_USE_REG_EXP_SEARCH_KEY)) { @@ -106,17 +106,15 @@ public void run() { } else { result = FileUtil.findAssociatedFiles(entries, extensions, dirs); } - + boolean foundAny = false; // Iterate over the entries: for (Entry> entryFilePair : result.entrySet()) { FileListTableModel tableModel; - String oldVal = entryFilePair.getKey().getField(Globals.FILE_FIELD); + Optional oldVal = entryFilePair.getKey().getFieldOptional(Globals.FILE_FIELD); if (singleTableModel == null) { tableModel = new FileListTableModel(); - if (oldVal != null) { - tableModel.setContent(oldVal); - } + oldVal.ifPresent(tableModel::setContent); } else { assert entries.size() == 1; tableModel = singleTableModel; @@ -146,7 +144,7 @@ public void run() { } FileListEntry flEntry = new FileListEntry(f.getName(), f.getPath(), type); tableModel.addEntry(tableModel.getRowCount(), flEntry); - + String newVal = tableModel.getStringRepresentation(); if (newVal.isEmpty()) { newVal = null; @@ -154,7 +152,7 @@ public void run() { if (ce != null) { // store undo information UndoableFieldChange change = new UndoableFieldChange(entryFilePair.getKey(), - Globals.FILE_FIELD, oldVal, newVal); + Globals.FILE_FIELD, oldVal.orElse(null), newVal); ce.addEdit(change); } // hack: if table model is given, do NOT modify entry @@ -167,12 +165,12 @@ public void run() { } } } - + // handle callbacks and dialog // FIXME: The ID signals if action was successful :/ final int id = foundAny ? 1 : 0; SwingUtilities.invokeLater(new Runnable() { - + @Override public void run() { if (diag != null) { diff --git a/src/main/java/net/sf/jabref/external/SynchronizeFileField.java b/src/main/java/net/sf/jabref/external/SynchronizeFileField.java index 0908a6c2c878..4fb72cd7c838 100644 --- a/src/main/java/net/sf/jabref/external/SynchronizeFileField.java +++ b/src/main/java/net/sf/jabref/external/SynchronizeFileField.java @@ -77,11 +77,8 @@ public class SynchronizeFileField extends AbstractWorker { private int entriesChangedCount; - private final Object[] brokenLinkOptions = { - Localization.lang("Ignore"), - Localization.lang("Assign new file"), - Localization.lang("Remove link"), - Localization.lang("Remove all broken links"), + private final Object[] brokenLinkOptions = {Localization.lang("Ignore"), Localization.lang("Assign new file"), + Localization.lang("Remove link"), Localization.lang("Remove all broken links"), Localization.lang("Quit synchronization")}; private boolean goOn = true; @@ -147,11 +144,11 @@ public void run() { boolean removeAllBroken = false; mainLoop: for (BibEntry aSel : sel) { panel.frame().setProgressBarValue(progress++); - final String old = aSel.getField(Globals.FILE_FIELD); + final Optional old = aSel.getFieldOptional(Globals.FILE_FIELD); // Check if a extension is set: - if ((old != null) && !(old.isEmpty())) { + if (old.isPresent() && !(old.get().isEmpty())) { FileListTableModel tableModel = new FileListTableModel(); - tableModel.setContentDontGuessTypes(old); + tableModel.setContentDontGuessTypes(old.get()); // We need to specify which directories to search in for Util.expandFilename: List dirsS = panel.getBibDatabaseContext().getFileDirectory(); @@ -253,14 +250,14 @@ public void run() { } } - if (!tableModel.getStringRepresentation().equals(old)) { + if (!tableModel.getStringRepresentation().equals(old.orElse(null))) { // The table has been modified. Store the change: String toSet = tableModel.getStringRepresentation(); if (toSet.isEmpty()) { - ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old, null)); + ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old.orElse(null), null)); aSel.clearField(Globals.FILE_FIELD); } else { - ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old, toSet)); + ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old.orElse(null), toSet)); aSel.setField(Globals.FILE_FIELD, toSet); } changedEntries.add(aSel); @@ -301,14 +298,10 @@ static class OptionsDialog extends JDialog { private final JButton cancel = new JButton(Localization.lang("Cancel")); private boolean canceled = true; private final BibDatabaseContext databaseContext; - private final JRadioButton autoSetUnset = new JRadioButton( - Localization.lang("Automatically set file links") + ". " - + Localization.lang("Do not overwrite existing links."), - true); - private final JRadioButton autoSetAll = new JRadioButton( - Localization.lang("Automatically set file links") + ". " - + Localization.lang("Allow overwriting existing links."), - false); + private final JRadioButton autoSetUnset = new JRadioButton(Localization.lang("Automatically set file links") + + ". " + Localization.lang("Do not overwrite existing links."), true); + private final JRadioButton autoSetAll = new JRadioButton(Localization.lang("Automatically set file links") + + ". " + Localization.lang("Allow overwriting existing links."), false); private final JRadioButton autoSetNone = new JRadioButton(Localization.lang("Do not automatically set"), false); private final JCheckBox checkLinks = new JCheckBox(Localization.lang("Check existing file links"), true); @@ -341,11 +334,13 @@ public void actionPerformed(ActionEvent e) { bg.add(autoSetNone); bg.add(autoSetAll); - FormLayout layout = new FormLayout("fill:pref", "pref, 2dlu, pref, 2dlu, pref, pref, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref"); + FormLayout layout = new FormLayout("fill:pref", + "pref, 2dlu, pref, 2dlu, pref, pref, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref"); FormBuilder builder = FormBuilder.create().layout(layout); - JLabel description = new JLabel("" + Localization.lang( - "Attempt to automatically set file links for your entries. Automatically setting works if " - + "a file in your file directory
    or a subdirectory is named identically to an entry's BibTeX key, plus extension.") + JLabel description = new JLabel("" + + Localization + .lang("Attempt to automatically set file links for your entries. Automatically setting works if " + + "a file in your file directory
    or a subdirectory is named identically to an entry's BibTeX key, plus extension.") + ""); builder.addSeparator(Localization.lang("Automatically set file links")).xy(1, 1); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ACS.java b/src/main/java/net/sf/jabref/logic/fulltext/ACS.java index a50f1d94a909..3ca52ece4a64 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ACS.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/ACS.java @@ -38,7 +38,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // DOI search - Optional doi = DOI.build(entry.getField("doi")); + Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); if(doi.isPresent()) { String source = String.format(SOURCE, doi.get().getDOI()); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java b/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java index 31b89895e945..9011d520bedc 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java @@ -40,9 +40,9 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // 1. DOI - Optional doi = DOI.build(entry.getField("doi")); + Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); // 2. Eprint - String eprint = entry.getField("eprint"); + Optional eprint = entry.getFieldOptional("eprint"); if (doi.isPresent()) { String doiString = doi.get().getDOI(); @@ -72,10 +72,10 @@ public Optional findFullText(BibEntry entry) throws IOException { } catch (UnirestException | ParserConfigurationException | SAXException | IOException e) { LOGGER.warn("arXiv DOI API request failed", e); } - } else if (eprint != null && !eprint.isEmpty()) { + } else if ((eprint.isPresent()) && !eprint.get().isEmpty()) { try { // only lookup on id field - Document doc = queryApi("id:" + eprint); + Document doc = queryApi("id:" + eprint.get()); // Lookup PDF link NodeList links = doc.getElementsByTagName("link"); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java index f2fc0b443b17..1f432a4985e1 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java @@ -44,7 +44,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Objects.requireNonNull(entry); Optional pdfLink = Optional.empty(); - Optional doi = DOI.build(entry.getField("doi")); + Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); if(doi.isPresent()) { String sciLink = doi.get().getURIAsASCIIString(); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java index 118655061bad..31999163cd84 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java @@ -41,9 +41,9 @@ public FindFullText(List fetcher) { public Optional findFullTextPDF(BibEntry entry) { // for accuracy, fetch DOI first but do not modify entry BibEntry clonedEntry = (BibEntry) entry.clone(); - String doi = clonedEntry.getField("doi"); + Optional doi = clonedEntry.getFieldOptional("doi"); - if (doi == null || !DOI.build(doi).isPresent()) { + if (!doi.isPresent() || !DOI.build(doi.get()).isPresent()) { CrossRef.findDOI(clonedEntry).ifPresent(e -> clonedEntry.setField("doi", e.getDOI())); } diff --git a/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java b/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java index 0b52057fc06e..4ca6152fbfec 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java @@ -35,7 +35,7 @@ public Optional findFullText(BibEntry entry) throws IOException { } String url = String.format(SEARCH_URL, - URLEncoder.encode(entry.getField("title"), StandardCharsets.UTF_8.name())); + URLEncoder.encode(entry.getFieldOptional("title").orElse(null), StandardCharsets.UTF_8.name())); Document doc = Jsoup.connect(url) .userAgent("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0") // don't identify as a crawler diff --git a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java b/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java index 28d542aab55c..a1fe02634523 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java @@ -36,9 +36,10 @@ public Optional findFullText(BibEntry entry) throws IOException { String stampString = ""; // Try URL first -- will primarily work for entries from the old IEEE search - if (entry.hasField("url")) { + Optional urlString = entry.getFieldOptional("url"); + if (urlString.isPresent()) { // Is the URL a direct link to IEEE? - Matcher matcher = STAMP_PATTERN.matcher(entry.getField("url")); + Matcher matcher = STAMP_PATTERN.matcher(urlString.get()); if (matcher.find()) { // Found it stampString = matcher.group(1); @@ -47,7 +48,7 @@ public Optional findFullText(BibEntry entry) throws IOException { // If not, try DOI if (stampString.isEmpty()) { - Optional doi = DOI.build(entry.getField("doi")); + Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); if (doi.isPresent() && doi.get().getDOI().startsWith(IEEE_DOI) && doi.get().getURI().isPresent()) { // Download the HTML page from IEEE String resolvedDOIPage = new URLDownload(doi.get().getURI().get().toURL()) diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java b/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java index 6d3448621c6f..eb74da8d659a 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java @@ -52,7 +52,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // Try unique DOI first - Optional doi = DOI.build(entry.getField("doi")); + Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); if(doi.isPresent()) { // Available in catalog? diff --git a/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java b/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java index ba04f85fec68..164b5509ea85 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java @@ -49,7 +49,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // Try unique DOI first - Optional doi = DOI.build(entry.getField("doi")); + Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); if(doi.isPresent()) { // Available in catalog? diff --git a/src/main/java/net/sf/jabref/model/DuplicateCheck.java b/src/main/java/net/sf/jabref/model/DuplicateCheck.java index a00fd0660ea2..d4653aefb41d 100644 --- a/src/main/java/net/sf/jabref/model/DuplicateCheck.java +++ b/src/main/java/net/sf/jabref/model/DuplicateCheck.java @@ -133,23 +133,27 @@ private static double[] compareFieldSet(String[] fields, BibEntry one, BibEntry } private static int compareSingleField(String field, BibEntry one, BibEntry two) { - String s1 = one.getField(field); - String s2 = two.getField(field); - if (s1 == null) { - if (s2 == null) { + Optional optionalStringOne = one.getFieldOptional(field); + Optional optionalStringTwo = two.getFieldOptional(field); + if (!optionalStringOne.isPresent()) { + if (!optionalStringTwo.isPresent()) { return EMPTY_IN_BOTH; } return EMPTY_IN_ONE; - } else if (s2 == null) { + } else if (!optionalStringTwo.isPresent()) { return EMPTY_IN_TWO; } + // Both strings present + String stringOne = optionalStringOne.get(); + String stringTwo = optionalStringTwo.get(); + if (InternalBibtexFields.getFieldExtras(field).contains(FieldProperties.PERSON_NAMES)) { // Specific for name fields. // Harmonise case: - String auth1 = AuthorList.fixAuthorLastNameOnlyCommas(s1, false).replace(" and ", " ").toLowerCase(); - String auth2 = AuthorList.fixAuthorLastNameOnlyCommas(s2, false).replace(" and ", " ").toLowerCase(); - double similarity = DuplicateCheck.correlateByWords(auth1, auth2); + String authorOne = AuthorList.fixAuthorLastNameOnlyCommas(stringOne, false).replace(" and ", " ").toLowerCase(); + String authorTwo = AuthorList.fixAuthorLastNameOnlyCommas(stringTwo, false).replace(" and ", " ").toLowerCase(); + double similarity = DuplicateCheck.correlateByWords(authorOne, authorTwo); if (similarity > 0.8) { return EQUAL; } @@ -158,9 +162,9 @@ private static int compareSingleField(String field, BibEntry one, BibEntry two) // Pages can be given with a variety of delimiters, "-", "--", " - ", " -- ". // We do a replace to harmonize these to a simple "-": // After this, a simple test for equality should be enough: - s1 = s1.replaceAll("[- ]+", "-"); - s2 = s2.replaceAll("[- ]+", "-"); - if (s1.equals(s2)) { + stringOne = stringOne.replaceAll("[- ]+", "-"); + stringTwo = stringTwo.replaceAll("[- ]+", "-"); + if (stringOne.equals(stringTwo)) { return EQUAL; } return NOT_EQUAL; @@ -168,17 +172,17 @@ private static int compareSingleField(String field, BibEntry one, BibEntry two) // We do not attempt to harmonize abbreviation state of the journal names, // but we remove periods from the names in case they are abbreviated with // and without dots: - s1 = s1.replace(".", "").toLowerCase(); - s2 = s2.replace(".", "").toLowerCase(); - double similarity = DuplicateCheck.correlateByWords(s1, s2); + stringOne = stringOne.replace(".", "").toLowerCase(); + stringTwo = stringTwo.replace(".", "").toLowerCase(); + double similarity = DuplicateCheck.correlateByWords(stringOne, stringTwo); if (similarity > 0.8) { return EQUAL; } return NOT_EQUAL; } else { - s1 = s1.toLowerCase(); - s2 = s2.toLowerCase(); - double similarity = DuplicateCheck.correlateByWords(s1, s2); + stringOne = stringOne.toLowerCase(); + stringTwo = stringTwo.toLowerCase(); + double similarity = DuplicateCheck.correlateByWords(stringOne, stringTwo); if (similarity > 0.8) { return EQUAL; } @@ -193,9 +197,9 @@ public static double compareEntriesStrictly(BibEntry one, BibEntry two) { int score = 0; for (String field : allFields) { - Object en = one.getField(field); - Object to = two.getField(field); - if (((en != null) && (to != null) && en.equals(to)) || ((en == null) && (to == null))) { + Optional stringOne = one.getFieldOptional(field); + Optional stringTwo = two.getFieldOptional(field); + if (stringOne.equals(stringTwo)) { score++; } } diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index ae3987e9c767..3f905e1560cb 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; @@ -395,7 +396,8 @@ public BibEntry resolveForStrings(BibEntry entry, boolean inPlace) { } for (String field : resultingEntry.getFieldNames()) { - resultingEntry.setField(field, this.resolveForStrings(resultingEntry.getField(field))); + resultingEntry.getFieldOptional(field) + .ifPresent(fieldValue -> resultingEntry.setField(field, this.resolveForStrings(fieldValue))); } return resultingEntry; } @@ -522,12 +524,16 @@ public static String getResolvedField(String field, BibEntry entry, BibDatabase // If this field is not set, and the entry has a crossref, try to look up the // field in the referred entry: Do not do this for the bibtex key. if ((o == null) && (database != null) && database.followCrossrefs && !field.equals(BibEntry.KEY_FIELD)) { - if (entry.hasField("crossref")) { - BibEntry referred = database.getEntryByKey(entry.getField("crossref")); + Optional crossrefKey = entry.getFieldOptional("crossref"); + if (crossrefKey.isPresent()) { + BibEntry referred = database.getEntryByKey(crossrefKey.get()); if (referred != null) { // Ok, we found the referred entry. Get the field value from that // entry. If it is unset there, too, stop looking: - o = referred.getField(field); + Optional crossrefContent = referred.getFieldOptional(field); + if (crossrefContent.isPresent()) { + o = crossrefContent.get(); + } } } } diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 16a3266d6c55..e6fa8a88b52f 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -580,7 +580,7 @@ public void addKeywords(Collection keywords) { } public Set getKeywords() { - return net.sf.jabref.model.entry.EntryUtil.getSeparatedKeywords(this.getField(KEYWORDS_FIELD)); + return net.sf.jabref.model.entry.EntryUtil.getSeparatedKeywords(this); } public Collection getFieldValues() { diff --git a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java index 3f50d01844c2..6d6bd11f63fa 100644 --- a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java +++ b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java @@ -43,4 +43,12 @@ public static Set getSeparatedKeywords(String keywordString) { } return keywords; } + + /** + * @param entry a BibEntry + * @return an List containing the keywords of the entry. An empty list if keywords are null or empty + */ + public static Set getSeparatedKeywords(BibEntry entry) { + return getSeparatedKeywords(entry.getFieldOptional(BibEntry.KEYWORDS_FIELD).orElse(null)); + } } diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java index 9ad407f5f82f..c2387f6f88f4 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java @@ -26,6 +26,7 @@ import net.sf.jabref.logic.util.UpdateField; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.EntryUtil; import static net.sf.jabref.model.entry.BibEntry.KEYWORDS_FIELD; @@ -85,14 +86,15 @@ public static void updateField(SpecialField e, String value, BibEntry be, NamedC UpdateField.updateField(be, e.getFieldName(), value, nullFieldIfValueIsTheSame) .ifPresent(fieldChange -> ce.addEdit(new UndoableFieldChange(fieldChange))); // we cannot use "value" here as updateField has side effects: "nullFieldIfValueIsTheSame" nulls the field if value is the same - SpecialFieldsUtils.exportFieldToKeywords(e, be.getField(e.getFieldName()), be, ce); + SpecialFieldsUtils.exportFieldToKeywords(e, be.getFieldOptional(e.getFieldName()).orElse(null), be, ce); } private static void exportFieldToKeywords(SpecialField e, BibEntry be, NamedCompound ce) { - SpecialFieldsUtils.exportFieldToKeywords(e, be.getField(e.getFieldName()), be, ce); + SpecialFieldsUtils.exportFieldToKeywords(e, be.getFieldOptional(e.getFieldName()).orElse(null), be, ce); } - private static void exportFieldToKeywords(SpecialField e, String newValue, BibEntry entry, NamedCompound ce) { + private static void exportFieldToKeywords(SpecialField e, String newValue, BibEntry entry, + NamedCompound ce) { if (!SpecialFieldsUtils.keywordSyncEnabled()) { return; } @@ -120,8 +122,8 @@ private static void exportFieldToKeywords(SpecialField e, String newValue, BibEn Optional change = entry.putKeywords(keywordList); - if (ce != null && change.isPresent()) { - ce.addEdit(new UndoableFieldChange(change.get())); + if (ce != null){ + change.ifPresent(changeValue -> ce.addEdit(new UndoableFieldChange(changeValue))); } } @@ -162,8 +164,7 @@ public static void syncSpecialFieldsFromKeywords(BibEntry be, NamedCompound ce) if (!be.hasField(KEYWORDS_FIELD)) { return; } - Set keywordList = net.sf.jabref.model.entry.EntryUtil - .getSeparatedKeywords(be.getField(KEYWORDS_FIELD)); + Set keywordList = EntryUtil.getSeparatedKeywords(be); SpecialFieldsUtils.importKeywordsForField(keywordList, Priority.getInstance(), be, ce); SpecialFieldsUtils.importKeywordsForField(keywordList, Rank.getInstance(), be, ce); SpecialFieldsUtils.importKeywordsForField(keywordList, Quality.getInstance(), be, ce); diff --git a/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java b/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java index 7064c839d447..0c00382b4a7e 100644 --- a/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java +++ b/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java @@ -24,5 +24,12 @@ public void getSeparatedKeywords() { Assert.assertEquals(new LinkedHashSet<>(Arrays.asList("w1", "w2a w2b", "w3")), separatedKeywords); } - + @Test + public void getSeparatedKeywordsEntry() { + String keywords = "w1, w2a w2b, w3"; + BibEntry entry = new BibEntry(); + entry.setField(BibEntry.KEYWORDS_FIELD, keywords); + Set separatedKeywords = EntryUtil.getSeparatedKeywords(entry); + Assert.assertEquals(new LinkedHashSet<>(Arrays.asList("w1", "w2a w2b", "w3")), separatedKeywords); + } } From 7a8b89d10b614843d252e9b66b6bc357918aa1e4 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 16:13:54 +0200 Subject: [PATCH 201/268] =?UTF-8?q?Some=20more=20testing=20of=20BibDatabas?= =?UTF-8?q?e,=20primarily=20related=20to=20DuplicationChe=E2=80=A6=20(#157?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Some more testing of BibDatabase, primarily related to DuplicationChecker * More tests related to resolving strings --- .../model/database/BibDatabaseTest.java | 120 ++++++++++++++++++ .../sf/jabref/model/entry/MonthUtilTest.java | 1 + 2 files changed, 121 insertions(+) diff --git a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java index d1dbb56a4db4..8106d11371f9 100644 --- a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java +++ b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java @@ -197,4 +197,124 @@ public void changingEntryPostsChangeEntryEvent() { assertEquals(entry, tel.getBibEntry()); } + + @Test + public void correctKeyCountOne() { + BibEntry entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + assertEquals(database.getNumberOfKeyOccurrences("AAA"), 1); + } + + @Test + public void correctKeyCountTwo() { + BibEntry entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + assertEquals(database.getNumberOfKeyOccurrences("AAA"), 2); + } + + @Test + public void setCiteKeySameKeySameEntry() { + BibEntry entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + assertFalse(database.setCiteKeyForEntry(entry, "AAA")); + assertEquals(database.getNumberOfKeyOccurrences("AAA"), 1); + } + + @Test + public void setCiteKeyRemoveKey() { + BibEntry entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + assertFalse(database.setCiteKeyForEntry(entry, null)); + assertEquals(database.getNumberOfKeyOccurrences("AAA"), 0); + assertNull(entry.getCiteKey()); + } + + @Test + public void setCiteKeyDifferentKeySameEntry() { + BibEntry entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + assertFalse(database.setCiteKeyForEntry(entry, "BBB")); + assertEquals(database.getNumberOfKeyOccurrences("AAA"), 0); + assertEquals(database.getNumberOfKeyOccurrences("BBB"), 1); + } + + + @Test + public void setCiteKeySameKeyDifferentEntries() { + BibEntry entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + entry = new BibEntry(); + entry.setCiteKey("BBB"); + database.insertEntry(entry); + assertTrue(database.setCiteKeyForEntry(entry, "AAA")); + assertEquals(entry.getCiteKey(), "AAA"); + assertEquals(database.getNumberOfKeyOccurrences("AAA"), 2); + assertEquals(database.getNumberOfKeyOccurrences("BBB"), 0); + } + + @Test + public void correctKeyCountAfterRemoving() { + BibEntry entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + entry = new BibEntry(); + entry.setCiteKey("AAA"); + database.insertEntry(entry); + database.removeEntry(entry); + assertEquals(database.getNumberOfKeyOccurrences("AAA"), 1); + } + + @Test + public void circularStringResolving() { + BibtexString string = new BibtexString(IdGenerator.next(), "AAA", "#BBB#"); + database.addString(string); + string = new BibtexString(IdGenerator.next(), "BBB", "#AAA#"); + database.addString(string); + assertEquals(database.resolveForStrings("#AAA#"), "AAA"); + assertEquals(database.resolveForStrings("#BBB#"), "BBB"); + } + + @Test + public void circularStringResolvingLongerCycle() { + BibtexString string = new BibtexString(IdGenerator.next(), "AAA", "#BBB#"); + database.addString(string); + string = new BibtexString(IdGenerator.next(), "BBB", "#CCC#"); + database.addString(string); + string = new BibtexString(IdGenerator.next(), "CCC", "#DDD#"); + database.addString(string); + string = new BibtexString(IdGenerator.next(), "DDD", "#AAA#"); + database.addString(string); + assertEquals(database.resolveForStrings("#AAA#"), "AAA"); + assertEquals(database.resolveForStrings("#BBB#"), "BBB"); + assertEquals(database.resolveForStrings("#CCC#"), "CCC"); + assertEquals(database.resolveForStrings("#DDD#"), "DDD"); + } + + @Test + public void resolveForStringsMonth() { + assertEquals(database.resolveForStrings("#jan#"), "January"); + } + + @Test + public void resolveForStringsSurroundingContent() { + BibtexString string = new BibtexString(IdGenerator.next(), "AAA", "aaa"); + database.addString(string); + assertEquals(database.resolveForStrings("aa#AAA#AAA"), "aaaaaAAA"); + } + + @Test + public void resolveForStringsOddHashMarkAtTheEnd() { + BibtexString string = new BibtexString(IdGenerator.next(), "AAA", "aaa"); + database.addString(string); + assertEquals(database.resolveForStrings("AAA#AAA#AAA#"), "AAAaaaAAA#"); + } } diff --git a/src/test/java/net/sf/jabref/model/entry/MonthUtilTest.java b/src/test/java/net/sf/jabref/model/entry/MonthUtilTest.java index 36e9a15bbb0a..043b259ca8e7 100644 --- a/src/test/java/net/sf/jabref/model/entry/MonthUtilTest.java +++ b/src/test/java/net/sf/jabref/model/entry/MonthUtilTest.java @@ -75,5 +75,6 @@ public void testToMonthNumber() { Assert.assertEquals(-1, MonthUtil.getMonth("#test#").index); Assert.assertEquals(-1, MonthUtil.getMonth("").index); Assert.assertFalse(MonthUtil.getMonth("8,").isValid()); + Assert.assertTrue(MonthUtil.getMonth("jan").isValid()); } } \ No newline at end of file From ac3139b39f0dcd3dd454e5a3a27c728ebbeb0524 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 11 Jul 2016 16:21:05 +0200 Subject: [PATCH 202/268] Removed support for optinally following crossrefs since it wasn't used (#1569) --- src/main/java/net/sf/jabref/gui/BasePanel.java | 1 - .../net/sf/jabref/model/database/BibDatabase.java | 11 +---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 6bb4d65094f0..4b7acbbb5bbd 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -585,7 +585,6 @@ public void run() { // Run third, on EDT: @Override public void update() { - database.setFollowCrossrefs(true); if (canceled) { frame.unblock(); return; diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index 3f905e1560cb..a32fe33c6445 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -85,11 +85,6 @@ public class BibDatabase { private final Set internalIDs = new HashSet<>(); - /** - * Configuration - */ - private boolean followCrossrefs = true; - private final EventBus eventBus = new EventBus(); /** @@ -523,7 +518,7 @@ public static String getResolvedField(String field, BibEntry entry, BibDatabase // If this field is not set, and the entry has a crossref, try to look up the // field in the referred entry: Do not do this for the bibtex key. - if ((o == null) && (database != null) && database.followCrossrefs && !field.equals(BibEntry.KEY_FIELD)) { + if ((o == null) && (database != null) && !field.equals(BibEntry.KEY_FIELD)) { Optional crossrefKey = entry.getFieldOptional("crossref"); if (crossrefKey.isPresent()) { BibEntry referred = database.getEntryByKey(crossrefKey.get()); @@ -555,10 +550,6 @@ public static String getText(String toResolve, BibDatabase database) { return toResolve; } - public void setFollowCrossrefs(boolean followCrossrefs) { - this.followCrossrefs = followCrossrefs; - } - public void setEpilog(String epilog) { this.epilog = epilog; } From aebe493c6a89e026ff11b4e51222a58c03ac4353 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Mon, 11 Jul 2016 16:32:32 +0200 Subject: [PATCH 203/268] Implements HTMLToUnicodeFormatter --- CHANGELOG.md | 1 + build.gradle | 2 + .../sf/jabref/logic/formatter/Formatters.java | 2 + .../bibtexfields/HtmlToUnicodeFormatter.java | 35 +++++++++++ .../HtmlToUnicodeFormatterTest.java | 59 +++++++++++++++++++ 5 files changed, 99 insertions(+) create mode 100644 src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java create mode 100644 src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 37019b266b11..020d53a2dc4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed +- Implemented [#1356](https://github.com/JabRef/jabref/issues/1356): Added a formatter for converting HTML to Unicode - Implemented [#661](https://github.com/JabRef/jabref/issues/661): Introducing a "check for updates" mechnism (manually/automatic at startup) - [#1485](https://github.com/JabRef/jabref/issues/1485): Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography - [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view diff --git a/build.gradle b/build.gradle index 1ae1da148e21..13bb16f323ac 100644 --- a/build.gradle +++ b/build.gradle @@ -103,6 +103,8 @@ dependencies { compile 'commons-logging:commons-logging:1.2' + compile 'org.apache.commons:commons-lang3:3.4' + compile 'org.jsoup:jsoup:1.9.2' compile 'com.mashape.unirest:unirest-java:1.4.9' compile 'info.debatty:java-string-similarity:0.13' diff --git a/src/main/java/net/sf/jabref/logic/formatter/Formatters.java b/src/main/java/net/sf/jabref/logic/formatter/Formatters.java index 8f7fda6d6f29..c4d704774099 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/Formatters.java +++ b/src/main/java/net/sf/jabref/logic/formatter/Formatters.java @@ -23,6 +23,7 @@ import net.sf.jabref.logic.formatter.bibtexfields.ClearFormatter; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; +import net.sf.jabref.logic.formatter.bibtexfields.HtmlToUnicodeFormatter; import net.sf.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeMonthFormatter; @@ -45,6 +46,7 @@ public class Formatters { public static final List CONVERTERS = Arrays.asList( new HtmlToLatexFormatter(), + new HtmlToUnicodeFormatter(), new LatexToUnicodeFormatter(), new UnicodeToLatexFormatter() ); diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java new file mode 100644 index 000000000000..c8fdc8d46e31 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java @@ -0,0 +1,35 @@ +package net.sf.jabref.logic.formatter.bibtexfields; + +import net.sf.jabref.logic.formatter.Formatter; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.layout.LayoutFormatter; +import org.apache.commons.lang3.StringEscapeUtils; + +public class HtmlToUnicodeFormatter implements LayoutFormatter, Formatter { + + @Override + public String getName() { + return "HTML to Unicode"; + } + + @Override + public String getKey() { + return "html_to_unicode"; + } + + @Override + public String getDescription() { + return Localization.lang("Converts HTML code to Unicode."); + } + + @Override + public String getExampleInput() { + return "bread & butter"; + } + + @Override + public String format(String fieldText) { + // StringEscapeUtils converts characters and regex kills tags + return StringEscapeUtils.unescapeHtml4(fieldText).replaceAll("\\<[^>]*>",""); + } +} diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java new file mode 100644 index 000000000000..52d69f41e746 --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java @@ -0,0 +1,59 @@ +package net.sf.jabref.logic.formatter.bibtexfields; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class HtmlToUnicodeFormatterTest { + + private final HtmlToUnicodeFormatter formatter = new HtmlToUnicodeFormatter(); + + @Before + public void setUp() throws Exception { + Globals.prefs = JabRefPreferences.getInstance(); + } + + @Test + public void formatWithoutHtmlCharactersReturnsSameString() { + assertEquals("abc", formatter.format("abc")); + } + + @Test + public void formatMultipleHtmlCharacters() { + assertEquals("åäö", formatter.format("åäö")); + } + + @Test + public void formatCombinedAccent() { + assertEquals("í", formatter.format("í")); + } + + @Test + public void testBasic() { + assertEquals("aaa", formatter.format("aaa")); + } + + @Test + public void testHTML() { + assertEquals("ä", formatter.format("ä")); + assertEquals("ä", formatter.format("ä")); + assertEquals("ä", formatter.format("ä")); + assertEquals("Ε", formatter.format("Ε")); + } + + @Test + public void testHTMLRemoveTags() { + assertEquals("aaa", formatter.format("

    aaa

    ")); + } + + @Test + public void formatExample() { + assertEquals("bread & butter", formatter.format(formatter.getExampleInput())); + } +} + + From 0ad5e6c5a100774dbba6f7d701378fc9cba5e19f Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Mon, 11 Jul 2016 16:45:53 +0200 Subject: [PATCH 204/268] Add missing localization --- .../logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java | 1 + src/main/resources/l10n/JabRef_da.properties | 2 ++ src/main/resources/l10n/JabRef_de.properties | 3 +++ src/main/resources/l10n/JabRef_en.properties | 1 + src/main/resources/l10n/JabRef_es.properties | 2 ++ src/main/resources/l10n/JabRef_fa.properties | 2 ++ src/main/resources/l10n/JabRef_fr.properties | 2 ++ src/main/resources/l10n/JabRef_in.properties | 2 ++ src/main/resources/l10n/JabRef_it.properties | 2 ++ src/main/resources/l10n/JabRef_ja.properties | 2 ++ src/main/resources/l10n/JabRef_nl.properties | 2 ++ src/main/resources/l10n/JabRef_no.properties | 2 ++ src/main/resources/l10n/JabRef_pt_BR.properties | 2 ++ src/main/resources/l10n/JabRef_ru.properties | 2 ++ src/main/resources/l10n/JabRef_sv.properties | 3 +++ src/main/resources/l10n/JabRef_tr.properties | 2 ++ src/main/resources/l10n/JabRef_vi.properties | 2 ++ src/main/resources/l10n/JabRef_zh.properties | 2 ++ 18 files changed, 36 insertions(+) diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java index c8fdc8d46e31..e570fab3093d 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatter.java @@ -3,6 +3,7 @@ import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.LayoutFormatter; + import org.apache.commons.lang3.StringEscapeUtils; public class HtmlToUnicodeFormatter implements LayoutFormatter, Formatter { diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index be1e215b013c..9105603bb4f3 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1705,3 +1705,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 052229cc30e6..6f44fcad7863 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2279,6 +2279,7 @@ Changes_the_first_letter_of_all_words_to_capital_case_and_the_remaining_letters_ Cleans_up_LaTeX_code.=Räumt_LaTeX-Code_auf. Converts_HTML_code_to_LaTeX_code.=Konvertiere_HTML-Code_in_LaTeX-Code. +Converts_HTML_code_to_Unicode.= Konvertiere_HTML-Code_in_Unicode. Converts_LaTeX_encoding_to_Unicode_characters.=Konvertiere_LaTeX_Kodierung_in_Unicode_Zeichen. Converts_Unicode_characters_to_LaTeX_encoding.=Konvertiere_Unicode_Zeichen_in_LaTeX_Kodierung. Converts_ordinals_to_LaTeX_superscripts.=Konvertiere_Ordinalzahlen_in_LaTeX_Hochstellung. @@ -2422,3 +2423,5 @@ The_link_has_been_copied_to_the_clipboard.=Der_Link_wurde_in_die_Zwischenablage_ Online_help_forum=Online-Hilfeforum Custom= + + diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index ec285564a4f6..c247bab1e772 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2148,6 +2148,7 @@ Changes_all_letters_to_upper_case.=Changes_all_letters_to_upper_case. Changes_the_first_letter_of_all_words_to_capital_case_and_the_remaining_letters_to_lower_case.=Changes_the_first_letter_of_all_words_to_capital_case_and_the_remaining_letters_to_lower_case. Cleans_up_LaTeX_code.=Cleans_up_LaTeX_code. Converts_HTML_code_to_LaTeX_code.=Converts_HTML_code_to_LaTeX_code. +Converts_HTML_code_to_Unicode.=Converts_HTML_code_to_Unicode. Converts_LaTeX_encoding_to_Unicode_characters.=Converts_LaTeX_encoding_to_Unicode_characters. Converts_Unicode_characters_to_LaTeX_encoding.=Converts_Unicode_characters_to_LaTeX_encoding. Converts_ordinals_to_LaTeX_superscripts.=Converts_ordinals_to_LaTeX_superscripts. diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 9d3e2fedf28f..d7165e77875e 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1607,3 +1607,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index a3f87222ddc0..29719dc6f9fc 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2393,3 +2393,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index d6a27fbda496..832d2df3c79d 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1651,3 +1651,5 @@ The_link_has_been_copied_to_the_clipboard.=Le_lien_a_été_copié_dans_le_presse Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 1244bdaa5271..41af879c375c 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1626,3 +1626,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 0eacdd6589de..bf6248f74b9f 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1726,3 +1726,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 19b1299db632..5f5d86e9cb21 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2371,3 +2371,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 87a6882a5c8b..56f8527cfa73 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2402,3 +2402,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index fc415c1ced27..3cb27e1d49cc 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2798,3 +2798,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index d48b41bf999d..3a79db535fac 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1620,3 +1620,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index fc3284ee02d6..8ed900dcb23e 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2370,3 +2370,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index cb76703aa2ff..c1cba58e6ca8 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1421,6 +1421,7 @@ Changes_all_letters_to_upper_case.=Ändrar_alla_bokstäver_till_versaler. Changes_the_first_letter_of_all_words_to_capital_case_and_the_remaining_letters_to_lower_case.= Cleans_up_LaTeX_code.=Städar_upp_i_LaTeX-koden. Converts_HTML_code_to_LaTeX_code.=Konverterar_HTML-koder_till_LaTeX-kod. +Converts_HTML_code_to_Unicode.=Konverterar_HTML-koder_till_Unicode-tecken. Converts_LaTeX_encoding_to_Unicode_characters.=Konverterar_Latex-koder_till_Unicode-tecken. Converts_Unicode_characters_to_LaTeX_encoding.=Konverterar_Unicode-tecken_till_LaTeX-kod. Converts_ordinals_to_LaTeX_superscripts.=Konverterar_ordningsnummer_till_LaTeX_\\superscript{}. @@ -1562,3 +1563,5 @@ The_link_has_been_copied_to_the_clipboard.=Länken_har_kopierats_till_urklipp. Online_help_forum=Onlineforum Custom=Egna + + diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 56ebc0dcf1d4..cafab5da9767 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1639,3 +1639,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 751b5df259b3..a5795fd668de 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2394,3 +2394,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index d9578dbbe2b8..91bbb8397f8b 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1633,3 +1633,5 @@ The_link_has_been_copied_to_the_clipboard.= Online_help_forum= Custom= + +Converts_HTML_code_to_Unicode.= From eddf636825a87bd2be7782971c0db306c6596245 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 12 Jul 2016 11:19:22 +0200 Subject: [PATCH 205/268] Added button to crossref entry editor field to select parent entry (#1563) * Added button to crossref entry editor field to select parent entry * And the main table column feature... --- CHANGELOG.md | 1 + .../jabref/gui/entryeditor/EntryEditor.java | 2 + .../gui/entryeditor/FieldExtraComponents.java | 57 +++++++++++++++++-- .../maintable/MainTableSelectionListener.java | 3 + .../jabref/model/entry/FieldProperties.java | 3 +- .../model/entry/InternalBibtexFields.java | 4 +- 6 files changed, 62 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37019b266b11..6aa06df4408f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Updated German translation - When resolving duplicate BibTeX-keys there is now an "Ignore" button. "Cancel" and close key now quits the resolving. - The [online forum](http://discourse.jabref.org/) is now directly accessible via the "Help" menu +- Implemented [#1338](https://github.com/JabRef/jabref/issues/1338): clicking on a crossref in the main table selects the parent entry and added a button in the entry editor to select the parent entry. ### Fixed - Fixed [#1530](https://github.com/JabRef/jabref/issues/1530): Unescaped hashes in the url field are ignored by the integrity checker diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 5716a75360f3..0e1f1c1eb4a9 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -529,6 +529,8 @@ public Optional getExtra(final FieldEditor editor) { return FieldExtraComponents.getPaginationExtraComponent(editor, this); } else if (fieldExtras.contains(FieldProperties.TYPE)) { return FieldExtraComponents.getTypeExtraComponent(editor, this, "patent".equalsIgnoreCase(entry.getType())); + } else if (fieldExtras.contains(FieldProperties.CROSSREF)) { + return FieldExtraComponents.getCrossrefExtraComponent(editor, frame.getCurrentBasePanel()); } return Optional.empty(); } diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index b4fd3baa8510..b6040c411061 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -134,7 +134,7 @@ public static Optional getExternalExtraComponent(BasePanel panel, Fi // enable/disable button JTextComponent url = (JTextComponent) fieldEditor; - DocumentListener documentListener = new DocumentListener() { + url.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent documentEvent) { checkUrl(); @@ -157,8 +157,7 @@ private void checkUrl() { button.setEnabled(false); } } - }; - url.getDocument().addDocumentListener(documentListener); + }); return Optional.of(controls); } @@ -205,7 +204,7 @@ public static Optional getDoiExtraComponent(BasePanel panel, EntryEd // enable/disable button JTextComponent doi = (JTextComponent) fieldEditor; - DocumentListener documentListener = new DocumentListener() { + doi.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent documentEvent) { checkDoi(); @@ -231,8 +230,7 @@ private void checkDoi() { fetchButton.setEnabled(false); } } - }; - doi.getDocument().addDocumentListener(documentListener); + }); return Optional.of(controls); } @@ -474,4 +472,51 @@ public static Optional getGenderExtraComponent(FieldEditor fieldEdit return Optional.of(gender); } + + /** + * Return a button which allows to go to the parent entry of the crossref field + * @param fieldEditor The FieldEditor component to get the entry key from + * @param panel The current BasePanel + * @return + */ + + public static Optional getCrossrefExtraComponent(FieldEditor fieldEditor, + BasePanel panel) { + JButton button = new JButton(Localization.lang("Select")); + JTextComponent crossref = (JTextComponent) fieldEditor; + + button.addActionListener( + actionEvent -> panel.highlightEntry(panel.getDatabase().getEntryByKey(crossref.getText()))); + + // enable/disable button + crossref.getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void changedUpdate(DocumentEvent documentEvent) { + checkValidKey(); + } + + @Override + public void insertUpdate(DocumentEvent documentEvent) { + checkValidKey(); + } + + @Override + public void removeUpdate(DocumentEvent documentEvent) { + checkValidKey(); + } + + private void checkValidKey() { + if (panel.getDatabase().getEntryByKey(crossref.getText()) != null) { + button.setEnabled(true); + } else { + button.setEnabled(false); + } + } + }); + + return Optional.of(button); + + } + } diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index 1bdb359a2be4..c66e29378a91 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -337,6 +337,9 @@ public void mouseClicked(MouseEvent e) { } } }); + } else if (modelColumn.getBibtexFields().contains("crossref")) { // Clicking on crossref column + tableRows.get(row).getFieldOptional("crossref") + .ifPresent(crossref -> panel.highlightEntry(panel.getDatabase().getEntryByKey(crossref))); } } diff --git a/src/main/java/net/sf/jabref/model/entry/FieldProperties.java b/src/main/java/net/sf/jabref/model/entry/FieldProperties.java index 1e1d190a8b63..972c687ae85f 100644 --- a/src/main/java/net/sf/jabref/model/entry/FieldProperties.java +++ b/src/main/java/net/sf/jabref/model/entry/FieldProperties.java @@ -22,7 +22,8 @@ public enum FieldProperties { DOI, EDITOR_TYPE, PAGINATION, - TYPE; + TYPE, + CROSSREF; public static final Set ALL_OPTS = EnumSet.allOf(FieldProperties.class); diff --git a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index 44708f03482a..c7c9d353337c 100644 --- a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -95,7 +95,9 @@ private InternalBibtexFields() { add(new BibtexSingleField("author", true, BibtexSingleField.MEDIUM_W, 280)); add(new BibtexSingleField("booktitle", true, 175)); add(new BibtexSingleField("chapter", true, BibtexSingleField.SMALL_W)); - add(new BibtexSingleField("crossref", true, BibtexSingleField.SMALL_W)); + dummy = new BibtexSingleField("crossref", true, BibtexSingleField.SMALL_W); + dummy.setExtras(EnumSet.of(FieldProperties.CROSSREF)); + add(dummy); add(new BibtexSingleField("edition", true, BibtexSingleField.SMALL_W)); add(new BibtexSingleField("editor", true, BibtexSingleField.MEDIUM_W, 280)); add(new BibtexSingleField("howpublished", true, BibtexSingleField.MEDIUM_W)); From aa42800140ce7b3c2dd1472f2e51e00c138a05bc Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 12 Jul 2016 11:24:27 +0200 Subject: [PATCH 206/268] Introduced Optional return values (#1573) * Introduced Optional return values --- .../java/net/sf/jabref/JabRefPreferences.java | 34 +++++++------------ src/main/java/net/sf/jabref/MetaData.java | 12 +++---- .../net/sf/jabref/bst/BibtexCaseChanger.java | 2 +- .../maintable/MainTableSelectionListener.java | 26 +++++++------- .../importer/fileformat/BibtexParser.java | 9 ++--- .../jabref/logic/CustomEntryTypesManager.java | 9 ++--- .../logic/fulltext/MimeTypeDetector.java | 11 +++--- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 6 ++-- .../jabref/model/entry/AuthorListParser.java | 26 +++++++------- .../net/sf/jabref/model/entry/BibEntry.java | 13 +++---- .../jabref/model/entry/CustomEntryType.java | 11 +++--- .../specialfields/SpecialFieldsUtils.java | 18 +++++----- .../sf/jabref/model/entry/BibEntryTests.java | 15 ++++---- 13 files changed, 92 insertions(+), 100 deletions(-) diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index c4d73e38bff4..497210c35bd6 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.prefs.BackingStoreException; import java.util.prefs.InvalidPreferencesFormatException; @@ -1013,10 +1014,10 @@ public List getStringList(String key) { StringReader rd = new StringReader(names); List res = new ArrayList<>(); - String rs; + Optional rs; try { - while ((rs = getNextUnit(rd)) != null) { - res.add(rs); + while ((rs = getNextUnit(rd)).isPresent()) { + res.add(rs.get()); } } catch (IOException ignored) { // Ignored @@ -1205,7 +1206,7 @@ private Object getObject(String key) { } - private static String getNextUnit(Reader data) throws IOException { + private static Optional getNextUnit(Reader data) throws IOException { // character last read // -1 if end of stream // initialization necessary, because of Java compiler @@ -1240,12 +1241,12 @@ private static String getNextUnit(Reader data) throws IOException { } } if (res.length() > 0) { - return res.toString(); + return Optional.of(res.toString()); } else if (c == -1) { // end of stream - return null; + return Optional.empty(); } else { - return ""; + return Optional.of(""); } } @@ -1265,22 +1266,22 @@ public void storeCustomEntryType(CustomEntryType tp, int number) { /** * Retrieves all information about the entry type in preferences, with the tag given by number. */ - public CustomEntryType getCustomEntryType(int number) { + public Optional getCustomEntryType(int number) { String nr = String.valueOf(number); String name = get(JabRefPreferences.CUSTOM_TYPE_NAME + nr); if (name == null) { - return null; + return Optional.empty(); } List req = getStringList(JabRefPreferences.CUSTOM_TYPE_REQ + nr); List opt = getStringList(JabRefPreferences.CUSTOM_TYPE_OPT + nr); List priOpt = getStringList(JabRefPreferences.CUSTOM_TYPE_PRIOPT + nr); if (priOpt.isEmpty()) { - return new CustomEntryType(EntryUtil.capitalizeFirst(name), req, opt); + return Optional.of(new CustomEntryType(EntryUtil.capitalizeFirst(name), req, opt)); } List secondary = new ArrayList<>(opt); secondary.removeAll(priOpt); - return new CustomEntryType(EntryUtil.capitalizeFirst(name), req, priOpt, secondary); + return Optional.of(new CustomEntryType(EntryUtil.capitalizeFirst(name), req, priOpt, secondary)); } @@ -1297,17 +1298,6 @@ public void purgeCustomEntryTypes(int number) { purgeSeries(JabRefPreferences.CUSTOM_TYPE_PRIOPT, number); } - public void purgeCustomEntryTypes() { - int number = 0; - if(getCustomEntryType(number) != null) { - number++; - } - - for(int i = 0; i < number; i++) { - purgeCustomEntryTypes(i); - } - } - /** * Removes all entries keyed by prefix+number, where number is equal to or higher than the given number. * diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index 61cc13e1b093..c4247fc45115 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -85,9 +85,9 @@ private MetaData(Map inData) throws ParseException { List orderedData = new ArrayList<>(); // We must allow for ; and \ in escape sequences. try { - String unit; - while ((unit = getNextUnit(data)) != null) { - orderedData.add(unit); + Optional unit; + while ((unit = getNextUnit(data)).isPresent()) { + orderedData.add(unit.get()); } } catch (IOException ex) { LOGGER.error("Weird error while parsing meta data.", ex); @@ -200,7 +200,7 @@ public void setGroups(GroupTreeNode root) { /** * Reads the next unit. Units are delimited by ';'. */ - private static String getNextUnit(Reader reader) throws IOException { + private static Optional getNextUnit(Reader reader) throws IOException { int c; boolean escape = false; StringBuilder res = new StringBuilder(); @@ -217,9 +217,9 @@ private static String getNextUnit(Reader reader) throws IOException { } } if (res.length() > 0) { - return res.toString(); + return Optional.of(res.toString()); } - return null; + return Optional.empty(); } public DBStrings getDBStrings() { diff --git a/src/main/java/net/sf/jabref/bst/BibtexCaseChanger.java b/src/main/java/net/sf/jabref/bst/BibtexCaseChanger.java index 8221595e4a0f..33784b7d60f5 100644 --- a/src/main/java/net/sf/jabref/bst/BibtexCaseChanger.java +++ b/src/main/java/net/sf/jabref/bst/BibtexCaseChanger.java @@ -280,7 +280,7 @@ private int convertCharIfBraceLevelIsZero(char[] c, int start, StringBuilder sb, /** * Determine whether there starts a special char at pos (e.g., oe, AE). Return it as string. - * If nothing found, return null + * If nothing found, return Optional.empty() * * Also used by BibtexPurify * diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index c66e29378a91..0e130c13d748 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -50,7 +50,6 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.specialfields.SpecialField; import net.sf.jabref.specialfields.SpecialFieldValue; import net.sf.jabref.specialfields.SpecialFieldsUtils; @@ -351,19 +350,20 @@ public void mouseClicked(MouseEvent e) { * @param columnName the name of the specialfield column */ private void handleSpecialFieldLeftClick(MouseEvent e, String columnName) { - SpecialField field = SpecialFieldsUtils.getSpecialFieldInstanceFromFieldName(columnName); - if ((e.getClickCount() == 1) && (field != null)) { - // special field found - if (field.isSingleValueField()) { - // directly execute toggle action instead of showing a menu with one action - field.getValues().get(0).getAction(panel.frame()).action(); - } else { - JPopupMenu menu = new JPopupMenu(); - for (SpecialFieldValue val : field.getValues()) { - menu.add(val.getMenuAction(panel.frame())); + if ((e.getClickCount() == 1)) { + SpecialFieldsUtils.getSpecialFieldInstanceFromFieldName(columnName).ifPresent(field -> { + // special field found + if (field.isSingleValueField()) { + // directly execute toggle action instead of showing a menu with one action + field.getValues().get(0).getAction(panel.frame()).action(); + } else { + JPopupMenu menu = new JPopupMenu(); + for (SpecialFieldValue val : field.getValues()) { + menu.add(val.getMenuAction(panel.frame())); + } + menu.show(table, e.getX(), e.getY()); } - menu.show(table, e.getX(), e.getY()); - } + }); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index f4c78b0c2f0a..788abd770693 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import net.sf.jabref.MetaData; import net.sf.jabref.importer.ParserResult; @@ -280,12 +281,12 @@ private void parseJabRefComment(Map meta) throws IOException { .equals(CustomEntryType.ENTRYTYPE_FLAG)) { // A custom entry type can also be stored in a // "@comment" - CustomEntryType typ = CustomEntryType.parse(comment); - if(typ == null) { + Optional typ = CustomEntryType.parse(comment); + if (typ.isPresent()) { + entryTypes.put(typ.get().getName(), typ.get()); + } else { parserResult.addWarning(Localization.lang("Ill-formed entrytype comment in bib file") + ": " + comment); - } else { - entryTypes.put(typ.getName(), typ); } // custom entry types are always re-written by JabRef and not stored in the file diff --git a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java b/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java index f26f17bcabe3..c59f6fa70c82 100644 --- a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java +++ b/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Optional; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.EntryTypes; @@ -19,10 +20,10 @@ public class CustomEntryTypesManager { */ public static void loadCustomEntryTypes(JabRefPreferences prefs) { int number = 0; - CustomEntryType type; - while ((type = prefs.getCustomEntryType(number)) != null) { - EntryTypes.addOrModifyCustomEntryType(type); - ALL.add(type); + Optional type; + while ((type = prefs.getCustomEntryType(number)).isPresent()) { + EntryTypes.addOrModifyCustomEntryType(type.get()); + ALL.add(type.get()); number++; } } diff --git a/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java b/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java index 7e7b444af429..e96269a6d09e 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.net.URL; import java.net.URLConnection; +import java.util.Optional; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -11,19 +12,19 @@ public class MimeTypeDetector { private static final Log LOGGER = LogFactory.getLog(MimeTypeDetector.class); public static boolean isPdfContentType(String url) { - String contentType = getMimeType(url); + Optional contentType = getMimeType(url); - return contentType != null && contentType.toLowerCase().startsWith("application/pdf"); + return contentType.isPresent() && contentType.get().toLowerCase().startsWith("application/pdf"); } - private static String getMimeType(String url) { + private static Optional getMimeType(String url) { try { URLConnection connection = new URL(url).openConnection(); - return connection.getContentType(); + return Optional.ofNullable(connection.getContentType()); } catch (IOException e) { LOGGER.debug("Error getting MIME type of URL", e); - return null; + return Optional.empty(); } } } \ No newline at end of file diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index 7c1017d105b1..24c62d8c465f 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -695,10 +695,8 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, * * Bibtex-Fields used: year, month */ - String publicationDate = entry.getPublicationDate(); - if (publicationDate != null) { - dcSchema.addSequenceValue("dc:date", publicationDate); - } + entry.getPublicationDate() + .ifPresent(publicationDate -> dcSchema.addSequenceValue("dc:date", publicationDate)); continue; } /** diff --git a/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java b/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java index 281961577393..de1f9a1bc746 100644 --- a/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java +++ b/src/main/java/net/sf/jabref/model/entry/AuthorListParser.java @@ -4,6 +4,7 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; public class AuthorListParser { @@ -26,7 +27,7 @@ public class AuthorListParser { /** true if upper-case token, false if lower-case */ private boolean tokenCase; - + // Constant HashSet containing names of TeX special characters private static final Set TEX_NAMES = new HashSet<>(); @@ -84,10 +85,7 @@ public AuthorList parse(String listOfNames) { // Parse author by author List authors = new ArrayList<>(5); // 5 seems to be reasonable initial size while (tokenStart < original.length()) { - Author author = getAuthor(); - if (author != null) { - authors.add(author); - } + getAuthor().ifPresent(authors::add); } return new AuthorList(authors); } @@ -95,10 +93,10 @@ public AuthorList parse(String listOfNames) { /** * Parses one author name and returns preformatted information. * - * @return Preformatted author name; null if author name is + * @return Preformatted author name; Optional.empty() if author name is * empty. */ - private Author getAuthor() { + private Optional getAuthor() { List tokens = new ArrayList<>(); // initialization int vonStart = -1; @@ -135,8 +133,8 @@ private Author getAuthor() { } if (vonStart < 0) { if (!tokenCase) { - int previousTermToken = tokens.size() - TOKEN_GROUP_LENGTH - TOKEN_GROUP_LENGTH + OFFSET_TOKEN_TERM; - if(previousTermToken >= 0 && tokens.get(previousTermToken).equals('-')) { + int previousTermToken = (tokens.size() - TOKEN_GROUP_LENGTH - TOKEN_GROUP_LENGTH) + OFFSET_TOKEN_TERM; + if((previousTermToken >= 0) && tokens.get(previousTermToken).equals('-')) { // We are in a first name which contained a hyphen break; } @@ -156,7 +154,7 @@ private Author getAuthor() { // Second step: split name into parts (here: calculate indices // of parts in 'tokens' Vector) if (tokens.isEmpty()) { - return null; // no author information + return Optional.empty(); // no author information } // the following negatives indicate absence of the corresponding part @@ -251,13 +249,13 @@ private Author getAuthor() { false); String jrPart = jrPartStart < 0 ? null : concatTokens(tokens, jrPartStart, jrPartEnd, OFFSET_TOKEN, false); - if(firstPart != null && lastPart != null && lastPart.equals(lastPart.toUpperCase()) && lastPart.length() < 5) { + if((firstPart != null) && (lastPart != null) && lastPart.equals(lastPart.toUpperCase()) && (lastPart.length() < 5)) { // The last part is a small string in complete upper case, so interpret it as initial of the first name // This is the case for example in "Smith SH" which we think of as lastname=Smith and firstname=SH // The length < 5 constraint should allow for "Smith S.H." as input - return new Author(lastPart, lastPart, vonPart, firstPart, jrPart); + return Optional.of(new Author(lastPart, lastPart, vonPart, firstPart, jrPart)); } else { - return new Author(firstPart, firstAbbr, vonPart, lastPart, jrPart); + return Optional.of(new Author(firstPart, firstAbbr, vonPart, lastPart, jrPart)); } } @@ -356,7 +354,7 @@ private int getToken() { if (c == '{') { bracesLevel++; } - if (firstLetterIsFound && (tokenAbbr < 0) && (bracesLevel == 0 || c == '{')) { + if (firstLetterIsFound && (tokenAbbr < 0) && ((bracesLevel == 0) || (c == '{'))) { tokenAbbr = tokenEnd; } if ((c == '}') && (bracesLevel > 0)) { diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index e6fa8a88b52f..6bdc0778baf5 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -497,17 +497,18 @@ public String getAuthorTitleYear(int maxCharacters) { * * @return will return the publication date of the entry or null if no year was found. */ - public String getPublicationDate() { + public Optional getPublicationDate() { if (!hasField("year")) { - return null; + return Optional.empty(); } - String year = getField("year"); + Optional year = getFieldOptional("year"); - if (hasField("month")) { - MonthUtil.Month month = MonthUtil.getMonth(getField("month")); + Optional monthString = getFieldOptional("month"); + if (monthString.isPresent()) { + MonthUtil.Month month = MonthUtil.getMonth(monthString.get()); if (month.isValid()) { - return year + "-" + month.twoDigitNumber; + return Optional.of(year.orElse("") + "-" + month.twoDigitNumber); } } return year; diff --git a/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java b/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java index 0e25356ba3c4..d7cb88c118a3 100644 --- a/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java +++ b/src/main/java/net/sf/jabref/model/entry/CustomEntryType.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -51,23 +52,23 @@ public CustomEntryType(String name, String required, String optional) { this(name, Arrays.asList(required.split(";")), Arrays.asList(optional.split(";"))); } - public static CustomEntryType parse(String comment) { + public static Optional parse(String comment) { String rest = comment.substring(ENTRYTYPE_FLAG.length()); int indexEndOfName = rest.indexOf(':'); if(indexEndOfName < 0) { - return null; + return Optional.empty(); } String fieldsDescription = rest.substring(indexEndOfName + 2); int indexEndOfRequiredFields = fieldsDescription.indexOf(']'); int indexEndOfOptionalFields = fieldsDescription.indexOf(']', indexEndOfRequiredFields + 1); - if (indexEndOfRequiredFields < 4 || indexEndOfOptionalFields < indexEndOfRequiredFields + 6) { - return null; + if ((indexEndOfRequiredFields < 4) || (indexEndOfOptionalFields < (indexEndOfRequiredFields + 6))) { + return Optional.empty(); } String name = rest.substring(0, indexEndOfName); String reqFields = fieldsDescription.substring(4, indexEndOfRequiredFields); String optFields = fieldsDescription.substring(indexEndOfRequiredFields + 6, indexEndOfOptionalFields); - return new CustomEntryType(name, reqFields, optFields); + return Optional.of(new CustomEntryType(name, reqFields, optFields)); } @Override diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java index c2387f6f88f4..731ecddcddae 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java @@ -177,21 +177,21 @@ public static void syncSpecialFieldsFromKeywords(BibEntry be, NamedCompound ce) * @param fieldName the fieldName * @return an instance of that field. The returned object is a singleton. null is returned if fieldName does not indicate a special field */ - public static SpecialField getSpecialFieldInstanceFromFieldName(String fieldName) { + public static Optional getSpecialFieldInstanceFromFieldName(String fieldName) { if (fieldName.equals(SpecialFieldsUtils.FIELDNAME_PRIORITY)) { - return Priority.getInstance(); + return Optional.of(Priority.getInstance()); } else if (fieldName.equals(SpecialFieldsUtils.FIELDNAME_QUALITY)) { - return Quality.getInstance(); + return Optional.of(Quality.getInstance()); } else if (fieldName.equals(SpecialFieldsUtils.FIELDNAME_RANKING)) { - return Rank.getInstance(); + return Optional.of(Rank.getInstance()); } else if (fieldName.equals(SpecialFieldsUtils.FIELDNAME_RELEVANCE)) { - return Relevance.getInstance(); + return Optional.of(Relevance.getInstance()); } else if (fieldName.equals(SpecialFieldsUtils.FIELDNAME_READ)) { - return ReadStatus.getInstance(); + return Optional.of(ReadStatus.getInstance()); } else if (fieldName.equals(SpecialFieldsUtils.FIELDNAME_PRINTED)) { - return Printed.getInstance(); + return Optional.of(Printed.getInstance()); } else { - return null; + return Optional.empty(); } } @@ -200,7 +200,7 @@ public static SpecialField getSpecialFieldInstanceFromFieldName(String fieldName * @return true if given field is a special field, false otherwise */ public static boolean isSpecialField(String fieldName) { - return SpecialFieldsUtils.getSpecialFieldInstanceFromFieldName(fieldName) != null; + return SpecialFieldsUtils.getSpecialFieldInstanceFromFieldName(fieldName).isPresent(); } public static boolean keywordSyncEnabled() { diff --git a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java index e1826638860f..4e450556373a 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java @@ -118,23 +118,24 @@ public void typeOfBibEntryIsMiscAfterSettingToEmptyString() { @Test public void testGetPublicationDate() { - Assert.assertEquals("2003-02", + Assert.assertEquals(Optional.of("2003-02"), (BibtexParser.singleFromString("@ARTICLE{HipKro03, year = {2003}, month = #FEB# }")) .getPublicationDate()); - Assert.assertEquals("2003-03", - (BibtexParser.singleFromString("@ARTICLE{HipKro03, year = {2003}, month = 3 }")).getPublicationDate()); + Assert.assertEquals(Optional.of("2003-03"), + (BibtexParser.singleFromString("@ARTICLE{HipKro03, year = {2003}, month = 3 }")).getPublicationDate() + ); - Assert.assertEquals("2003", + Assert.assertEquals(Optional.of("2003"), (BibtexParser.singleFromString("@ARTICLE{HipKro03, year = {2003}}")).getPublicationDate()); - Assert.assertEquals(null, + Assert.assertEquals(Optional.empty(), (BibtexParser.singleFromString("@ARTICLE{HipKro03, month = 3 }")).getPublicationDate()); - Assert.assertEquals(null, + Assert.assertEquals(Optional.empty(), (BibtexParser.singleFromString("@ARTICLE{HipKro03, author={bla}}")).getPublicationDate()); - Assert.assertEquals("2003-12", + Assert.assertEquals(Optional.of("2003-12"), (BibtexParser.singleFromString("@ARTICLE{HipKro03, year = {2003}, month = #DEC# }")) .getPublicationDate()); From 59b8af85f5dfad184da58122a5b00900732ab3d9 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 12 Jul 2016 11:41:06 +0200 Subject: [PATCH 207/268] Remove invalid space in german localization --- src/main/resources/l10n/JabRef_de.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 6f44fcad7863..6bdc28a96ada 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2279,7 +2279,7 @@ Changes_the_first_letter_of_all_words_to_capital_case_and_the_remaining_letters_ Cleans_up_LaTeX_code.=Räumt_LaTeX-Code_auf. Converts_HTML_code_to_LaTeX_code.=Konvertiere_HTML-Code_in_LaTeX-Code. -Converts_HTML_code_to_Unicode.= Konvertiere_HTML-Code_in_Unicode. +Converts_HTML_code_to_Unicode.=Konvertiere_HTML-Code_in_Unicode. Converts_LaTeX_encoding_to_Unicode_characters.=Konvertiere_LaTeX_Kodierung_in_Unicode_Zeichen. Converts_Unicode_characters_to_LaTeX_encoding.=Konvertiere_Unicode_Zeichen_in_LaTeX_Kodierung. Converts_ordinals_to_LaTeX_superscripts.=Konvertiere_Ordinalzahlen_in_LaTeX_Hochstellung. From 0f6e0a620e1f3eefc61f20076a3994679644a7bb Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 12 Jul 2016 11:55:04 +0200 Subject: [PATCH 208/268] Add HtmlToUnicodeFormatter to FormatterTests class --- src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java index 0142d235a2fc..bb3dbbec3964 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java @@ -7,6 +7,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.formatter.bibtexfields.ClearFormatter; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; +import net.sf.jabref.logic.formatter.bibtexfields.HtmlToUnicodeFormatter; import net.sf.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeMonthFormatter; @@ -105,6 +106,7 @@ public static Collection instancesToTest() { new Object[]{new CapitalizeFormatter()}, new Object[]{new ClearFormatter()}, new Object[]{new HtmlToLatexFormatter()}, + new Object[]{new HtmlToUnicodeFormatter()}, new Object[]{new IdentityFormatter()}, new Object[]{new LatexCleanupFormatter()}, new Object[]{new LatexToUnicodeFormatter()}, From 8f2f36f7a32e5d46d2d83d9e876e88a61eaa0111 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 12 Jul 2016 11:55:20 +0200 Subject: [PATCH 209/268] Use setUp methods in all formatter tests --- .../logic/formatter/IdentityFormatterTest.java | 9 ++++++++- .../OrdinalsToSuperscriptFormatterTest.java | 8 +++++++- .../formatter/bibtexfields/ClearFormatterTest.java | 7 ++++++- .../bibtexfields/HtmlToLatexFormatterTest.java | 12 +++++++++--- .../bibtexfields/HtmlToUnicodeFormatterTest.java | 6 +++--- .../bibtexfields/LatexCleanupFormatterTest.java | 8 +++++++- .../bibtexfields/NormalizeDateFormatterTest.java | 8 +++++++- .../bibtexfields/NormalizeMonthFormatterTest.java | 8 +++++++- .../bibtexfields/NormalizeNamesFormatterTest.java | 8 +++++++- .../bibtexfields/NormalizePagesFormatterTest.java | 8 +++++++- .../bibtexfields/RemoveBracesFormatterTest.java | 7 ++++++- .../formatter/bibtexfields/UnicodeConverterTest.java | 10 ++++++++-- .../bibtexfields/UnicodeToLatexFormatterTest.java | 8 +++++++- .../bibtexfields/UnitsToLatexFormatterTest.java | 7 ++++++- .../casechanger/CapitalizeFormatterTest.java | 9 ++++++++- .../casechanger/LowerCaseFormatterTest.java | 8 +++++++- .../casechanger/ProtectTermsFormatterTest.java | 8 +++++++- .../casechanger/SentenceCaseFormatterTest.java | 8 +++++++- .../casechanger/TitleCaseFormatterTest.java | 8 +++++++- .../casechanger/UpperCaseFormatterTest.java | 8 +++++++- .../minifier/MinifyNameListFormatterTest.java | 9 ++++++++- 21 files changed, 146 insertions(+), 26 deletions(-) diff --git a/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java index 02cb2cce2e86..729c039f1388 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java @@ -1,6 +1,8 @@ package net.sf.jabref.logic.formatter; +import net.sf.jabref.logic.formatter.casechanger.UpperCaseFormatter; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -10,7 +12,12 @@ */ public class IdentityFormatterTest { - private final IdentityFormatter formatter = new IdentityFormatter(); + private IdentityFormatter formatter; + + @Before + public void setUp() { + formatter = new IdentityFormatter(); + } @Test public void formatExample() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/OrdinalsToSuperscriptFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/OrdinalsToSuperscriptFormatterTest.java index 85fbc5ceecd5..e5543eea8b17 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/OrdinalsToSuperscriptFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/OrdinalsToSuperscriptFormatterTest.java @@ -4,6 +4,7 @@ import net.sf.jabref.logic.formatter.bibtexfields.OrdinalsToSuperscriptFormatter; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -13,7 +14,12 @@ */ public class OrdinalsToSuperscriptFormatterTest { - private final OrdinalsToSuperscriptFormatter formatter = new OrdinalsToSuperscriptFormatter(); + private OrdinalsToSuperscriptFormatter formatter; + + @Before + public void setUp() { + formatter = new OrdinalsToSuperscriptFormatter(); + } @Test public void replacesSuperscript() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/ClearFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/ClearFormatterTest.java index f675200d0bb2..7666dc52b817 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/ClearFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/ClearFormatterTest.java @@ -4,14 +4,19 @@ * Tests in addition to the general tests from {@link net.sf.jabref.logic.formatter.FormatterTest} */ +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; public class ClearFormatterTest { - private final ClearFormatter formatter = new ClearFormatter(); + private ClearFormatter formatter; + @Before + public void setUp() { + formatter = new ClearFormatter(); + } /** * Check whether the clear formatter really returns the empty string for the empty string diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java index 75785edb2365..e9e3c3d25175 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java @@ -4,6 +4,7 @@ import net.sf.jabref.JabRefPreferences; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -13,13 +14,18 @@ */ public class HtmlToLatexFormatterTest { - private final HtmlToLatexFormatter formatter = new HtmlToLatexFormatter(); + private HtmlToLatexFormatter formatter; - @Before - public void setUp() throws Exception { + @BeforeClass + public static void setUpBeforeClass() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); } + @Before + public void setUp() { + formatter = new HtmlToLatexFormatter(); + } + @Test public void formatWithoutHtmlCharactersReturnsSameString() { assertEquals("abc", formatter.format("abc")); diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java index 52d69f41e746..fd2da6cadf23 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java @@ -10,11 +10,11 @@ public class HtmlToUnicodeFormatterTest { - private final HtmlToUnicodeFormatter formatter = new HtmlToUnicodeFormatter(); + private HtmlToUnicodeFormatter formatter; @Before - public void setUp() throws Exception { - Globals.prefs = JabRefPreferences.getInstance(); + public void setUp() { + formatter = new HtmlToUnicodeFormatter(); } @Test diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/LatexCleanupFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/LatexCleanupFormatterTest.java index b22f5fca99fe..d840f14f525a 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/LatexCleanupFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/LatexCleanupFormatterTest.java @@ -1,5 +1,6 @@ package net.sf.jabref.logic.formatter.bibtexfields; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -9,7 +10,12 @@ */ public class LatexCleanupFormatterTest { - private final LatexCleanupFormatter formatter = new LatexCleanupFormatter(); + private LatexCleanupFormatter formatter; + + @Before + public void setUp() { + formatter = new LatexCleanupFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeDateFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeDateFormatterTest.java index 049ae95c401b..34347ae6aaa8 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeDateFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeDateFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.bibtexfields; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -8,7 +9,12 @@ */ public class NormalizeDateFormatterTest { - private final NormalizeDateFormatter formatter = new NormalizeDateFormatter(); + private NormalizeDateFormatter formatter; + + @Before + public void setUp() { + formatter = new NormalizeDateFormatter(); + } @Test public void formatDateYYYYMM0D() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeMonthFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeMonthFormatterTest.java index 15f464c5618a..5b44ede9a9bd 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeMonthFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeMonthFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.bibtexfields; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -8,7 +9,12 @@ */ public class NormalizeMonthFormatterTest { - private final NormalizeMonthFormatter formatter = new NormalizeMonthFormatter(); + private NormalizeMonthFormatter formatter; + + @Before + public void setUp() { + formatter = new NormalizeMonthFormatter(); + } @Test public void formatExample() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeNamesFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeNamesFormatterTest.java index a62d73b1f8e9..316578eef599 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeNamesFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizeNamesFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.bibtexfields; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -10,7 +11,12 @@ */ public class NormalizeNamesFormatterTest { - private final NormalizeNamesFormatter formatter = new NormalizeNamesFormatter(); + private NormalizeNamesFormatter formatter; + + @Before + public void setUp() { + formatter = new NormalizeNamesFormatter(); + } @Test public void testNormalizeAuthorList() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java index 8a72fc6f8661..1d564f770353 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/NormalizePagesFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.bibtexfields; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -8,7 +9,12 @@ */ public class NormalizePagesFormatterTest { - private final NormalizePagesFormatter formatter = new NormalizePagesFormatter(); + private NormalizePagesFormatter formatter; + + @Before + public void setUp() { + formatter = new NormalizePagesFormatter(); + } @Test public void formatSinglePageResultsInNoChange() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/RemoveBracesFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/RemoveBracesFormatterTest.java index 184286fb0015..babe39f74245 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/RemoveBracesFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/RemoveBracesFormatterTest.java @@ -1,5 +1,6 @@ package net.sf.jabref.logic.formatter.bibtexfields; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -10,8 +11,12 @@ */ public class RemoveBracesFormatterTest { - private final RemoveBracesFormatter formatter = new RemoveBracesFormatter(); + private RemoveBracesFormatter formatter; + @Before + public void setUp() { + formatter = new RemoveBracesFormatter(); + } @Test public void formatRemovesSingleEnclosingBraces() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java index 4d14e4aa2895..f6ca840b1804 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java @@ -4,6 +4,7 @@ import net.sf.jabref.JabRefPreferences; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -14,11 +15,16 @@ */ public class UnicodeConverterTest { - private final UnicodeToLatexFormatter formatter = new UnicodeToLatexFormatter(); + private UnicodeToLatexFormatter formatter; + + @BeforeClass + public static void setUpBeforeClass() { + Globals.prefs = JabRefPreferences.getInstance(); + } @Before public void setUp() { - Globals.prefs = JabRefPreferences.getInstance(); + formatter = new UnicodeToLatexFormatter(); } @Test diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatterTest.java index 4ebe38668295..d57f4403e06f 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatterTest.java @@ -1,5 +1,6 @@ package net.sf.jabref.logic.formatter.bibtexfields; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -9,7 +10,12 @@ */ public class UnicodeToLatexFormatterTest { - private final UnicodeToLatexFormatter formatter = new UnicodeToLatexFormatter(); + private UnicodeToLatexFormatter formatter; + + @Before + public void setUp() { + formatter = new UnicodeToLatexFormatter(); + } @Test public void formatWithoutUnicodeCharactersReturnsSameString() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnitsToLatexFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnitsToLatexFormatterTest.java index df007180cf05..df1fc337c4bd 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnitsToLatexFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnitsToLatexFormatterTest.java @@ -1,5 +1,6 @@ package net.sf.jabref.logic.formatter.bibtexfields; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -10,8 +11,12 @@ */ public class UnitsToLatexFormatterTest { - private final UnitsToLatexFormatter formatter = new UnitsToLatexFormatter(); + private UnitsToLatexFormatter formatter; + @Before + public void setUp() { + formatter = new UnitsToLatexFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java index f309aec3be78..5934d920d977 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java @@ -1,6 +1,8 @@ package net.sf.jabref.logic.formatter.casechanger; +import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -8,7 +10,12 @@ */ public class CapitalizeFormatterTest { - private final CapitalizeFormatter formatter = new CapitalizeFormatter(); + private CapitalizeFormatter formatter; + + @Before + public void setUp() { + formatter = new CapitalizeFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/LowerCaseFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/LowerCaseFormatterTest.java index df8fee1c9a1d..e67caf906aae 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/LowerCaseFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/LowerCaseFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.casechanger; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -8,7 +9,12 @@ */ public class LowerCaseFormatterTest { - private final LowerCaseFormatter formatter = new LowerCaseFormatter(); + private LowerCaseFormatter formatter; + + @Before + public void setUp() { + formatter = new LowerCaseFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java index cf31ae6ae35f..b52af7fdb836 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/ProtectTermsFormatterTest.java @@ -1,5 +1,6 @@ package net.sf.jabref.logic.formatter.casechanger; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -10,7 +11,12 @@ */ public class ProtectTermsFormatterTest { - private final ProtectTermsFormatter formatter = new ProtectTermsFormatter(); + private ProtectTermsFormatter formatter; + + @Before + public void setUp() { + formatter = new ProtectTermsFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/SentenceCaseFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/SentenceCaseFormatterTest.java index c2e104f48816..3b746674dace 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/SentenceCaseFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/SentenceCaseFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.casechanger; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; @@ -9,7 +10,12 @@ */ public class SentenceCaseFormatterTest { - private final SentenceCaseFormatter formatter = new SentenceCaseFormatter(); + private SentenceCaseFormatter formatter; + + @Before + public void setUp() { + formatter = new SentenceCaseFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/TitleCaseFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/TitleCaseFormatterTest.java index d020afc12279..d500d4635a7c 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/TitleCaseFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/TitleCaseFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.casechanger; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -8,7 +9,12 @@ */ public class TitleCaseFormatterTest { - private final TitleCaseFormatter formatter = new TitleCaseFormatter(); + private TitleCaseFormatter formatter; + + @Before + public void setUp() { + formatter = new TitleCaseFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/UpperCaseFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/UpperCaseFormatterTest.java index 3a0fcae2287c..bbccad51d66c 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/UpperCaseFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/UpperCaseFormatterTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.logic.formatter.casechanger; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; @@ -9,7 +10,12 @@ */ public class UpperCaseFormatterTest { - private final UpperCaseFormatter formatter = new UpperCaseFormatter(); + private UpperCaseFormatter formatter; + + @Before + public void setUp() { + formatter = new UpperCaseFormatter(); + } @Test public void test() { diff --git a/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java index e917c70854ea..29ddaad16bd1 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java @@ -1,6 +1,8 @@ package net.sf.jabref.logic.formatter.minifier; +import net.sf.jabref.logic.formatter.casechanger.UpperCaseFormatter; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -8,7 +10,12 @@ */ public class MinifyNameListFormatterTest { - private final MinifyNameListFormatter formatter = new MinifyNameListFormatter(); + private MinifyNameListFormatter formatter; + + @Before + public void setUp() { + formatter = new MinifyNameListFormatter(); + } @Test public void minifyAuthorNames() { From 11eb5f05635a3ff24e1e9814a74a1561aa2b9ab6 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 12 Jul 2016 11:59:15 +0200 Subject: [PATCH 210/268] Separate tests in HtmlToUnicodeFormatterTest --- .../formatter/bibtexfields/HtmlToUnicodeFormatterTest.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java index fd2da6cadf23..8037ec85edfb 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java @@ -38,10 +38,15 @@ public void testBasic() { } @Test - public void testHTML() { + public void testUmlauts() { assertEquals("ä", formatter.format("ä")); assertEquals("ä", formatter.format("ä")); assertEquals("ä", formatter.format("ä")); + + } + + @Test + public void testGreekLetter() { assertEquals("Ε", formatter.format("Ε")); } From 89a34fd62358eaac5666ae8685aedc3a7672a003 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 12 Jul 2016 12:03:41 +0200 Subject: [PATCH 211/268] Remove unused imports --- .../net/sf/jabref/logic/formatter/IdentityFormatterTest.java | 2 -- .../logic/formatter/casechanger/CapitalizeFormatterTest.java | 1 - .../logic/formatter/minifier/MinifyNameListFormatterTest.java | 1 - 3 files changed, 4 deletions(-) diff --git a/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java index 729c039f1388..8e24d35ca186 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/IdentityFormatterTest.java @@ -1,7 +1,5 @@ package net.sf.jabref.logic.formatter; - -import net.sf.jabref.logic.formatter.casechanger.UpperCaseFormatter; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java index 5934d920d977..9c7abc7c8c52 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/casechanger/CapitalizeFormatterTest.java @@ -1,6 +1,5 @@ package net.sf.jabref.logic.formatter.casechanger; -import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java index 29ddaad16bd1..40844f298010 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/minifier/MinifyNameListFormatterTest.java @@ -1,6 +1,5 @@ package net.sf.jabref.logic.formatter.minifier; -import net.sf.jabref.logic.formatter.casechanger.UpperCaseFormatter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; From ab003b0203ef75120bfcc9c11fb4a6fc078e92b4 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 12 Jul 2016 12:05:46 +0200 Subject: [PATCH 212/268] Move OrdinalsToSuperscriptFormatterTest into correct package --- .../OrdinalsToSuperscriptFormatterTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename src/test/java/net/sf/jabref/logic/formatter/{ => bibtexfields}/OrdinalsToSuperscriptFormatterTest.java (94%) diff --git a/src/test/java/net/sf/jabref/logic/formatter/OrdinalsToSuperscriptFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/OrdinalsToSuperscriptFormatterTest.java similarity index 94% rename from src/test/java/net/sf/jabref/logic/formatter/OrdinalsToSuperscriptFormatterTest.java rename to src/test/java/net/sf/jabref/logic/formatter/bibtexfields/OrdinalsToSuperscriptFormatterTest.java index e5543eea8b17..cd09805e9015 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/OrdinalsToSuperscriptFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/OrdinalsToSuperscriptFormatterTest.java @@ -1,7 +1,4 @@ -package net.sf.jabref.logic.formatter; - - -import net.sf.jabref.logic.formatter.bibtexfields.OrdinalsToSuperscriptFormatter; +package net.sf.jabref.logic.formatter.bibtexfields; import org.junit.Assert; import org.junit.Before; From 7c1afffe89e568e7a2e53b9f675ecc3e6f280b46 Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Tue, 12 Jul 2016 12:16:06 +0200 Subject: [PATCH 213/268] Remove more unused imports --- .../formatter/bibtexfields/HtmlToUnicodeFormatterTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java index 8037ec85edfb..85c0994baab4 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java @@ -1,8 +1,5 @@ package net.sf.jabref.logic.formatter.bibtexfields; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; - import org.junit.Before; import org.junit.Test; From 8e49aa622f3efd750fa98fc7bd5021ebe48c5398 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Tue, 12 Jul 2016 13:58:31 +0200 Subject: [PATCH 214/268] Fixed undo when update time stamp on edit is enabled (#1576) --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aa06df4408f..57e789922fe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1507](https://github.com/JabRef/jabref/issues/1507): Keywords are now separated by the delimiter specified in the preferences - Fixed [#1484](https://github.com/JabRef/jabref/issues/1484): HTML export handles some UTF characters wrong - Fixed [#1534](https://github.com/JabRef/jabref/issues/1534): "Mark entries imported into database" does not work correctly +- Fixed issue where field changes were not undoable if the time stamp was updated on editing ### Removed diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 0e1f1c1eb4a9..0563224e6e9e 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -1126,6 +1126,7 @@ public void actionPerformed(ActionEvent event) { ce.addEdit(undoableKeyChange); TimeStamp.doUpdateTimeStamp(entry) .ifPresent(fieldChange -> ce.addEdit(new UndoableFieldChange(fieldChange))); + ce.end(); panel.getUndoManager().addEdit(ce); } else { panel.getUndoManager().addEdit(undoableKeyChange); @@ -1193,8 +1194,10 @@ public void actionPerformed(ActionEvent event) { TimeStamp.doUpdateTimeStamp(entry) .ifPresent(fieldChange -> ce.addEdit(new UndoableFieldChange(fieldChange))); + ce.end(); panel.getUndoManager().addEdit(ce); + } else { panel.getUndoManager().addEdit(undoableFieldChange); } From e056602e54eb31fc2fd8e75b867a9a582e652ad1 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 13 Jul 2016 10:04:25 +0200 Subject: [PATCH 215/268] =?UTF-8?q?Added=20getEntryByKeyOptional=20and=20u?= =?UTF-8?q?sed=20it.=20Changed=20result=20of=20getFieldOr=E2=80=A6=20(#156?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added getEntryByKeyOptional and used it. Changed result of getFieldOrAlias to be Optional * Simplified getEntryByKey * Converted the final calls to use Optional --- .../jabref/gui/maintable/MainTableColumn.java | 10 ++-- .../sf/jabref/gui/openoffice/OOBibBase.java | 45 +++++++++-------- .../sf/jabref/logic/auxparser/AuxParser.java | 21 ++++---- .../bibtex/comparator/FieldComparator.java | 7 +-- .../jabref/logic/cleanup/BiblatexCleanup.java | 44 +++++++++-------- .../logic/labelpattern/LabelPatternUtil.java | 9 ++-- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 11 ++--- .../sf/jabref/model/database/BibDatabase.java | 32 +++++------- .../net/sf/jabref/model/entry/BibEntry.java | 49 +++++++++---------- .../java/net/sf/jabref/BibtexTestData.java | 2 +- .../external/RegExpFileSearchTests.java | 2 +- .../importer/DatabaseFileLookupTest.java | 4 +- .../importer/OpenDatabaseActionTest.java | 7 +-- .../logic/openoffice/OOBibStyleTest.java | 4 +- .../net/sf/jabref/logic/xmp/XMPUtilTest.java | 43 ++++++++-------- .../sf/jabref/model/entry/BibEntryTests.java | 26 +++++----- 16 files changed, 161 insertions(+), 155 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java index 69f906fd88fb..e8ca7aa169e4 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableColumn.java @@ -112,9 +112,13 @@ public Object getColumnValue(BibEntry entry) { if (field.equals(BibEntry.TYPE_HEADER)) { content = EntryUtil.capitalizeFirst(entry.getType()); } else { - content = entry.getFieldOrAlias(field); - if (database.isPresent() && "Author".equalsIgnoreCase(columnName) && (content != null)) { - content = database.get().resolveForStrings(content); + Optional newContent = entry.getFieldOrAlias(field); + if (newContent.isPresent()) { + if (database.isPresent() && "Author".equalsIgnoreCase(columnName)) { + content = database.get().resolveForStrings(newContent.get()); + } else { + content = newContent.get(); + } } } if (content != null) { diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java index 827a74e55407..fc0c8a52ef36 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java @@ -486,11 +486,13 @@ private List refreshCiteMarkersInternal(List databases, OOB BibEntry[] cEntries = new BibEntry[keys.length]; for (int j = 0; j < cEntries.length; j++) { BibDatabase database = linkSourceBase.get(keys[j]); - cEntries[j] = null; + Optional tmpEntry = Optional.empty(); if (database != null) { - cEntries[j] = database.getEntryByKey(keys[j]); + tmpEntry = database.getEntryByKey(keys[j]); } - if (cEntries[j] == null) { + if (tmpEntry.isPresent()) { + cEntries[j] = tmpEntry.get(); + } else { LOGGER.info("BibTeX key not found: '" + keys[j] + '\''); LOGGER.info("Problem with reference mark: '" + names.get(i) + '\''); cEntries[j] = new UndefinedBibtexEntry(keys[j]); @@ -641,29 +643,32 @@ private List refreshCiteMarkersInternal(List databases, OOB seenBefore.add(currentKey); } String uniq = uniquefiers.get(currentKey); + Optional tmpEntry = Optional.empty(); if (uniq == null) { if (firstLimAuthors[k] > 0) { needsChange = true; BibDatabase database = linkSourceBase.get(currentKey); if (database != null) { - cEntries[k] = database.getEntryByKey(currentKey); + tmpEntry = database.getEntryByKey(currentKey); } - uniquif[k] = ""; } else { BibDatabase database = linkSourceBase.get(currentKey); if (database != null) { - cEntries[k] = database.getEntryByKey(currentKey); + tmpEntry = database.getEntryByKey(currentKey); } - uniquif[k] = ""; } + uniquif[k] = ""; } else { needsChange = true; BibDatabase database = linkSourceBase.get(currentKey); if (database != null) { - cEntries[k] = database.getEntryByKey(currentKey); + tmpEntry = database.getEntryByKey(currentKey); } uniquif[k] = uniq; } + if (tmpEntry.isPresent()) { + cEntries[k] = tmpEntry.get(); + } } if (needsChange) { citMarkers[j] = style.getCitationMarker(Arrays.asList(cEntries), entries, @@ -798,9 +803,9 @@ private Map findCitedEntries(List databases, for (String key : keys) { boolean found = false; for (BibDatabase database : databases) { - BibEntry entry = database.getEntryByKey(key); - if (entry != null) { - entries.put(entry, database); + Optional entry = database.getEntryByKey(key); + if (entry.isPresent()) { + entries.put(entry.get(), database); linkSourceBase.put(key, database); found = true; break; @@ -845,18 +850,18 @@ private Map getSortedEntriesFromSortedRefMarks(List origEntry = Optional.empty(); if (database != null) { origEntry = database.getEntryByKey(key); } - if (origEntry == null) { + if (origEntry.isPresent()) { + if (!newList.containsKey(origEntry.get())) { + newList.put(origEntry.get(), database); + } + } else { LOGGER.info("BibTeX key not found: '" + key + "'"); LOGGER.info("Problem with reference mark: '" + name + "'"); newList.put(new UndefinedBibtexEntry(key), null); - } else { - if (!newList.containsKey(origEntry)) { - newList.put(origEntry, database); - } } } } @@ -1202,9 +1207,9 @@ public void combineCiteMarkers(List databases, OOBibStyle style) th List entries = new ArrayList<>(); for (String key : keys) { for (BibDatabase database : databases) { - BibEntry entry = database.getEntryByKey(key); - if (entry != null) { - entries.add(entry); + Optional entry = database.getEntryByKey(key); + if (entry.isPresent()) { + entries.add(entry.get()); break; } } diff --git a/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java b/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java index 5596c1bb8487..0c3778fe4d81 100644 --- a/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java +++ b/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java @@ -8,6 +8,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -126,13 +127,13 @@ private AuxParserResult parseAuxFile() { */ private void resolveTags(AuxParserResult result) { for (String key : result.getUniqueKeys()) { - BibEntry entry = masterDatabase.getEntryByKey(key); + Optional entry = masterDatabase.getEntryByKey(key); - if (entry == null) { - result.getUnresolvedKeys().add(key); + if (entry.isPresent()) { + insertEntry(entry.get(), result); + resolveCrossReferences(entry.get(), result); } else { - insertEntry(entry, result); - resolveCrossReferences(entry, result); + result.getUnresolvedKeys().add(key); } } @@ -149,13 +150,13 @@ private void resolveTags(AuxParserResult result) { private void resolveCrossReferences(BibEntry entry, AuxParserResult result) { entry.getFieldOptional("crossref").ifPresent(crossref -> { if (!result.getUniqueKeys().contains(crossref)) { - BibEntry refEntry = masterDatabase.getEntryByKey(crossref); + Optional refEntry = masterDatabase.getEntryByKey(crossref); - if (refEntry == null) { - result.getUnresolvedKeys().add(crossref); - } else { - insertEntry(refEntry, result); + if (refEntry.isPresent()) { + insertEntry(refEntry.get(), result); result.increaseCrossRefEntriesCounter(); + } else { + result.getUnresolvedKeys().add(crossref); } } }); diff --git a/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java index 8d5357a282e6..6ea66ddb816e 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java @@ -21,6 +21,7 @@ import java.util.Comparator; import java.util.Locale; import java.util.Objects; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.logic.config.SaveOrderConfig; @@ -170,9 +171,9 @@ public int compare(BibEntry e1, BibEntry e2) { private String getField(BibEntry entry) { for (String aField : field) { - String o = entry.getFieldOrAlias(aField); - if (o != null) { - return o; + Optional o = entry.getFieldOrAlias(aField); + if (o.isPresent()) { + return o.get(); } } return null; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java index 3de5e4bd51d9..eccb9dbc2f2e 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; @@ -33,34 +34,35 @@ public List cleanup(BibEntry entry) { for (Map.Entry alias : EntryConverter.FIELD_ALIASES_TEX_TO_LTX.entrySet()) { String oldFieldName = alias.getKey(); String newFieldName = alias.getValue(); - String oldValue = entry.getField(oldFieldName); - String newValue = entry.getField(newFieldName); - if ((oldValue != null) && (!oldValue.isEmpty()) && (newValue == null)) { - // There is content in the old field and no value in the new, so just copy - entry.setField(newFieldName, oldValue); - changes.add(new FieldChange(entry, newFieldName, null, oldValue)); + entry.getFieldOptional(oldFieldName).ifPresent(oldValue -> { + if (!oldValue.isEmpty() && (!entry.getFieldOptional(newFieldName).isPresent())) { + // There is content in the old field and no value in the new, so just copy + entry.setField(newFieldName, oldValue); + changes.add(new FieldChange(entry, newFieldName, null, oldValue)); - entry.clearField(oldFieldName); - changes.add(new FieldChange(entry, oldFieldName, oldValue, null)); - } + entry.clearField(oldFieldName); + changes.add(new FieldChange(entry, oldFieldName, oldValue, null)); + } + }); } // Dates: create date out of year and month, save it and delete old fields - if ((!entry.hasField("date")) || (entry.getField("date").isEmpty())) { - String newDate = entry.getFieldOrAlias("date"); - String oldYear = entry.getField("year"); - String oldMonth = entry.getField("month"); + entry.getFieldOptional("date").ifPresent(date -> { + if (date.isEmpty()) { + entry.getFieldOrAlias("date").ifPresent(newDate -> { + Optional oldYear = entry.getFieldOptional("year"); + Optional oldMonth = entry.getFieldOptional("month"); - if (newDate != null) { - entry.setField("date", newDate); - entry.clearField("year"); - entry.clearField("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)); + changes.add(new FieldChange(entry, "date", null, newDate)); + changes.add(new FieldChange(entry, "year", oldYear.orElse(null), null)); + changes.add(new FieldChange(entry, "month", oldMonth.orElse(null), null)); + }); } - } + }); return changes; } } diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index 7c15e9f86fb7..6e4c93f831e1 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -746,9 +746,9 @@ else if (val.matches("edtr\\d+")) { } else if ("veryshorttitle".equals(val)) { return getTitleWords(1, entry.getField("title")); } else if ("shortyear".equals(val)) { - String ss = entry.getFieldOrAlias("year"); - if (ss == null) { - return ""; + String ss = entry.getFieldOrAlias("year").orElse(""); + if (ss.isEmpty()) { + return ss; } else if (ss.startsWith("in") || ss.startsWith("sub")) { return "IP"; } else if (ss.length() > 2) { @@ -808,8 +808,7 @@ else if (val.matches("edtr\\d+")) { * @return The field value. */ private static String getField(BibEntry entry, String field) { - String s = entry.getFieldOrAlias(field); - return s == null ? "" : s; + return entry.getFieldOrAlias(field).orElse(""); } /** diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index 24c62d8c465f..4a764f9b4d9f 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -1255,15 +1255,14 @@ public static void main(String[] args) throws IOException, TransformerException ParserResult result = BibtexParser.parse(new FileReader(args[1])); - BibEntry bibEntry = result.getDatabase().getEntryByKey(args[0]); + Optional bibEntry = result.getDatabase().getEntryByKey(args[0]); - if (bibEntry == null) { - System.err.println("Could not find BibEntry " + args[0] - + " in " + args[0]); - } else { - XMPUtil.writeXMP(new File(args[2]), bibEntry, result.getDatabase()); + if (bibEntry.isPresent()) { + XMPUtil.writeXMP(new File(args[2]), bibEntry.get(), result.getDatabase()); System.out.println("XMP written."); + } else { + System.err.println("Could not find BibEntry " + args[0] + " in " + args[0]); } break; diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index a32fe33c6445..4db5e2036d28 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -141,17 +141,13 @@ public Set getAllVisibleFields() { /** * Returns the entry with the given bibtex key. */ - public synchronized BibEntry getEntryByKey(String key) { - BibEntry back = null; - - int keyHash = key.hashCode(); // key hash for better performance - + public synchronized Optional getEntryByKey(String key) { for (BibEntry entry : entries) { - if ((entry != null) && (entry.getCiteKey() != null) && (keyHash == entry.getCiteKey().hashCode())) { - back = entry; + if (key.equals(entry.getCiteKey())) { + return Optional.of(entry); } } - return back; + return Optional.empty(); } public synchronized List getEntriesByKey(String key) { @@ -390,9 +386,8 @@ public BibEntry resolveForStrings(BibEntry entry, boolean inPlace) { resultingEntry = (BibEntry) entry.clone(); } - for (String field : resultingEntry.getFieldNames()) { - resultingEntry.getFieldOptional(field) - .ifPresent(fieldValue -> resultingEntry.setField(field, this.resolveForStrings(fieldValue))); + for (Map.Entry field : resultingEntry.getFieldMap().entrySet()) { + resultingEntry.setField(field.getKey(), this.resolveForStrings(field.getValue())); } return resultingEntry; } @@ -514,26 +509,23 @@ public static String getResolvedField(String field, BibEntry entry, BibDatabase // TODO: Changed this to also consider alias fields, which is the expected // behavior for the preview layout and for the check whatever all fields are present. // But there might be unwanted side-effects?! - Object o = entry.getFieldOrAlias(field); + Optional result = entry.getFieldOrAlias(field); // If this field is not set, and the entry has a crossref, try to look up the // field in the referred entry: Do not do this for the bibtex key. - if ((o == null) && (database != null) && !field.equals(BibEntry.KEY_FIELD)) { + if (!result.isPresent() && (database != null) && !field.equals(BibEntry.KEY_FIELD)) { Optional crossrefKey = entry.getFieldOptional("crossref"); if (crossrefKey.isPresent()) { - BibEntry referred = database.getEntryByKey(crossrefKey.get()); - if (referred != null) { + Optional referred = database.getEntryByKey(crossrefKey.get()); + if (referred.isPresent()) { // Ok, we found the referred entry. Get the field value from that // entry. If it is unset there, too, stop looking: - Optional crossrefContent = referred.getFieldOptional(field); - if (crossrefContent.isPresent()) { - o = crossrefContent.get(); - } + result = referred.get().getFieldOptional(field); } } } - return BibDatabase.getText((String) o, database); + return BibDatabase.getText(result.orElse(null), database); } /** diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 6bdc0778baf5..134102f32bd5 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -225,14 +225,14 @@ private String toLowerCase(String fieldName) { *

    * The following aliases are considered (old bibtex <-> new biblatex) based * on the BibLatex documentation, chapter 2.2.5: - * address <-> location - * annote <-> annotation - * archiveprefix <-> eprinttype - * journal <-> journaltitle - * key <-> sortkey - * pdf <-> file - * primaryclass <-> eprintclass - * school <-> institution + * address <-> location + * annote <-> annotation + * archiveprefix <-> eprinttype + * journal <-> journaltitle + * key <-> sortkey + * pdf <-> file + * primaryclass <-> eprintclass + * school <-> institution * These work bidirectional. *

    * Special attention is paid to dates: (see the BibLatex documentation, @@ -241,10 +241,10 @@ private String toLowerCase(String fieldName) { * field is empty. Conversely, getFieldOrAlias("year") also tries to * extract the year from the 'date' field (analogously for 'month'). */ - public String getFieldOrAlias(String name) { - String fieldValue = getField(toLowerCase(name)); + public Optional getFieldOrAlias(String name) { + Optional fieldValue = getFieldOptional(toLowerCase(name)); - if (!Strings.isNullOrEmpty(fieldValue)) { + if (fieldValue.isPresent() && !fieldValue.get().isEmpty()) { return fieldValue; } @@ -252,7 +252,7 @@ public String getFieldOrAlias(String name) { String aliasForField = EntryConverter.FIELD_ALIASES.get(name); if (aliasForField != null) { - return getField(aliasForField); + return getFieldOptional(aliasForField); } // Finally, handle dates @@ -261,16 +261,16 @@ public String getFieldOrAlias(String name) { MonthUtil.Month month = MonthUtil.getMonth(getField("month")); if (year != null) { if (month.isValid()) { - return year + '-' + month.twoDigitNumber; + return Optional.of(year + '-' + month.twoDigitNumber); } else { - return year; + return Optional.of(year); } } } if ("year".equals(name) || "month".equals(name)) { - String date = getField("date"); - if (date == null) { - return null; + Optional date = getFieldOptional("date"); + if (!date.isPresent()) { + return Optional.empty(); } // Create date format matching dates with year and month @@ -281,7 +281,6 @@ public String getFieldOrAlias(String name) { final SimpleDateFormat sdf1 = new SimpleDateFormat(FORMAT1); final SimpleDateFormat sdf2 = new SimpleDateFormat(FORMAT2); - @Override public StringBuffer format(Date dDate, StringBuffer toAppendTo, FieldPosition fieldPosition) { throw new UnsupportedOperationException(); @@ -297,33 +296,33 @@ public Date parse(String source, ParsePosition pos) { }; try { - Date parsedDate = df.parse(date); + Date parsedDate = df.parse(date.get()); Calendar calendar = Calendar.getInstance(); calendar.setTime(parsedDate); if ("year".equals(name)) { - return Integer.toString(calendar.get(Calendar.YEAR)); + return Optional.of(Integer.toString(calendar.get(Calendar.YEAR))); } if ("month".equals(name)) { - return Integer.toString(calendar.get(Calendar.MONTH) + 1); // Shift by 1 since in this calendar Jan = 0 + return Optional.of(Integer.toString(calendar.get(Calendar.MONTH) + 1)); // Shift by 1 since in this calendar Jan = 0 } } catch (ParseException e) { // So not a date with year and month, try just to parse years df = new SimpleDateFormat("yyyy"); try { - Date parsedDate = df.parse(date); + Date parsedDate = df.parse(date.get()); Calendar calendar = Calendar.getInstance(); calendar.setTime(parsedDate); if ("year".equals(name)) { - return Integer.toString(calendar.get(Calendar.YEAR)); + return Optional.of(Integer.toString(calendar.get(Calendar.YEAR))); } } catch (ParseException e2) { LOGGER.warn("Could not parse entry " + name, e2); - return null; // Date field not in valid format + return Optional.empty(); // Date field not in valid format } } } - return null; + return Optional.empty(); } /** diff --git a/src/test/java/net/sf/jabref/BibtexTestData.java b/src/test/java/net/sf/jabref/BibtexTestData.java index 11dae647a1a7..9ef192efcea1 100644 --- a/src/test/java/net/sf/jabref/BibtexTestData.java +++ b/src/test/java/net/sf/jabref/BibtexTestData.java @@ -12,7 +12,7 @@ public class BibtexTestData { public static BibEntry getBibtexEntry() throws IOException { BibDatabase database = getBibtexDatabase(); - return database.getEntryByKey("HipKro03"); + return database.getEntryByKey("HipKro03").get(); } public static BibDatabase getBibtexDatabase() throws IOException { diff --git a/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java b/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java index bf216b0bfa96..9da81f6624ea 100644 --- a/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java +++ b/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java @@ -66,7 +66,7 @@ public void setUp() throws IOException { result = parser.parse(); database = result.getDatabase(); - entry = database.getEntryByKey("HipKro03"); + entry = database.getEntryByKey("HipKro03").get(); Assert.assertNotNull(database); Assert.assertNotNull(entry); diff --git a/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java b/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java index 06cda1063ae3..000ad0e86fa1 100644 --- a/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java +++ b/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java @@ -40,8 +40,8 @@ public void setUp() throws FileNotFoundException, IOException { database = result.getDatabase(); entries = database.getEntries(); - entry1 = database.getEntryByKey("entry1"); - entry2 = database.getEntryByKey("entry2"); + entry1 = database.getEntryByKey("entry1").get(); + entry2 = database.getEntryByKey("entry2").get(); } } diff --git a/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java b/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java index 2fb9f4a729bb..687dfef9285e 100644 --- a/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java +++ b/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java @@ -7,6 +7,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import java.util.Collection; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; @@ -74,7 +75,7 @@ public void entriesAreParsedNoHeader() throws IOException { // Entry Assert.assertEquals(1, db.getEntryCount()); - Assert.assertEquals("2014", db.getEntryByKey("1").getField("year")); + Assert.assertEquals(Optional.of("2014"), db.getEntryByKey("1").get().getFieldOptional("year")); } @Test @@ -84,7 +85,7 @@ public void entriesAreParsedHeader() throws IOException { // Entry Assert.assertEquals(1, db.getEntryCount()); - Assert.assertEquals("2014", db.getEntryByKey("1").getField("year")); + Assert.assertEquals(Optional.of("2014"), db.getEntryByKey("1").get().getFieldOptional("year")); } @Test @@ -94,7 +95,7 @@ public void entriesAreParsedHeaderAndSignature() throws IOException { // Entry Assert.assertEquals(1, db.getEntryCount()); - Assert.assertEquals("2014", db.getEntryByKey("1").getField("year")); + Assert.assertEquals(Optional.of("2014"), db.getEntryByKey("1").get().getFieldOptional("year")); } /** diff --git a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java index 0b4851dc049a..0e9e6aac7eaf 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java @@ -154,7 +154,7 @@ public void testGetCitationMarker() throws IOException { entryDBMap.put(entry, db); } - BibEntry entry = db.getEntryByKey("1137631"); + BibEntry entry = db.getEntryByKey("1137631").get(); assertEquals("[Boström et al., 2006]", style.getCitationMarker(Arrays.asList(entry), entryDBMap, true, null, null)); assertEquals("Boström et al. [2006]", @@ -173,7 +173,7 @@ public void testLayout() throws IOException { Layout l = style.getReferenceFormat("default"); l.setPostFormatter(new OOPreFormatter()); - BibEntry entry = db.getEntryByKey("1137631"); + BibEntry entry = db.getEntryByKey("1137631").get(); assertEquals( "Boström, G.; Wäyrynen, J.; Bodén, M.; Beznosov, K. and Kruchten, P. (2006). Extending XP practices to support security requirements engineering, : 11-18.", l.doLayout(entry, db)); diff --git a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java index ec91879e7670..95fbfbc4a6e1 100644 --- a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java @@ -273,8 +273,9 @@ public void testReadXMPSimple() throws COSVisitorException, IOException { Assert.assertNotNull(e); Assert.assertEquals("OezbekC06", e.getCiteKey()); - Assert.assertEquals("2003", e.getField("year")); - Assert.assertEquals("Beach sand convolution by surf-wave optimzation", e.getField("title")); + Assert.assertEquals(Optional.of("2003"), e.getFieldOptional("year")); + Assert.assertEquals(Optional.of("Beach sand convolution by surf-wave optimzation"), + e.getFieldOptional("title")); Assert.assertEquals("misc", e.getType()); } @@ -297,8 +298,8 @@ public void testReadXMPUTF8() throws COSVisitorException, IOException { Assert.assertNotNull(e); Assert.assertEquals("OezbekC06", e.getCiteKey()); - Assert.assertEquals("2003", e.getField("year")); - Assert.assertEquals("�pt�mz�t��n", e.getField("title")); + Assert.assertEquals(Optional.of("2003"), e.getFieldOptional("year")); + Assert.assertEquals(Optional.of("�pt�mz�t��n"), e.getFieldOptional("title")); Assert.assertEquals("misc", e.getType()); } @@ -371,8 +372,8 @@ public void testReadXMPSeq() throws COSVisitorException, IOException { Assert.assertNotNull(e); Assert.assertEquals("Clarkson06", e.getCiteKey()); - Assert.assertEquals("Kelly Clarkson and Ozzy Osbourne", e.getField("author")); - Assert.assertEquals("Huey Duck and Dewey Duck and Louie Duck", e.getField("editor")); + Assert.assertEquals("Kelly Clarkson and Ozzy Osbourne", e.getFieldOptional("author").get()); + Assert.assertEquals("Huey Duck and Dewey Duck and Louie Duck", e.getFieldOptional("editor").get()); Assert.assertEquals("misc", e.getType()); } @@ -491,9 +492,9 @@ public void testNewlineHandling() throws COSVisitorException, IOException { BibEntry e = l.get(0); Assert.assertNotNull(e); - Assert.assertEquals("Hallo World this is not an exercise .", e.getField("title")); - Assert.assertEquals("Hallo World this is not an exercise .", e.getField("tabs")); - Assert.assertEquals("\n\nAbstract preserve\n\t Whitespace\n\n", e.getField("abstract")); + Assert.assertEquals("Hallo World this is not an exercise .", e.getFieldOptional("title").get()); + Assert.assertEquals("Hallo World this is not an exercise .", e.getFieldOptional("tabs").get()); + Assert.assertEquals("\n\nAbstract preserve\n\t Whitespace\n\n", e.getFieldOptional("abstract").get()); } /** @@ -758,11 +759,12 @@ public void assertEqualsBibtexEntry(BibEntry expected, BibEntry actual) { if ("author".equalsIgnoreCase(field) || "editor".equalsIgnoreCase(field)) { - AuthorList expectedAuthors = AuthorList.parse(expected.getField(field)); - AuthorList actualAuthors = AuthorList.parse(actual.getField(field)); + AuthorList expectedAuthors = AuthorList.parse(expected.getFieldOptional(field).get()); + AuthorList actualAuthors = AuthorList.parse(actual.getFieldOptional(field).get()); Assert.assertEquals(expectedAuthors, actualAuthors); } else { - Assert.assertEquals("comparing " + field, expected.getField(field), actual.getField(field)); + Assert.assertEquals("comparing " + field, expected.getFieldOptional(field), + actual.getFieldOptional(field)); } } @@ -814,12 +816,12 @@ public void testXMPreadString() throws Exception { } Assert.assertEquals("canh05", a.getCiteKey()); - Assert.assertEquals("K. Crowston and H. Annabi", a.getField("author")); - Assert.assertEquals("Title A", a.getField("title")); + Assert.assertEquals("K. Crowston and H. Annabi", a.getFieldOptional("author").get()); + Assert.assertEquals("Title A", a.getFieldOptional("title").get()); Assert.assertEquals("article", a.getType()); Assert.assertEquals("foo", b.getCiteKey()); - Assert.assertEquals("Norton Bar", b.getField("author")); + Assert.assertEquals("Norton Bar", b.getFieldOptional("author").get()); Assert.assertEquals("inproceedings", b.getType()); } @@ -1319,7 +1321,7 @@ public void testResolveStrings() throws IOException, TransformerException { BibEntry x = l.get(0); Assert.assertEquals(AuthorList.parse("Crowston, K. and Annabi, H. and Howison, J. and Masango, C."), - AuthorList.parse(x.getField("author"))); + AuthorList.parse(x.getFieldOptional("author").get())); } @Test(expected = EncryptedPdfsNotSupportedException.class) @@ -1355,12 +1357,13 @@ public void testResolveStrings2() throws IOException, TransformerException { "Patterson, David and Arvind and Asanov\\'\\i{}c, Krste and Chiou, Derek and Hoe, James and Kozyrakis, Christos and Lu, S{hih-Lien} and Oskin, Mark and Rabaey, Jan and Wawrzynek, John"); try { - XMPUtil.writeXMP(pdfFile, result.getDatabase().getEntryByKey("Patterson06"), result.getDatabase()); + XMPUtil.writeXMP(pdfFile, result.getDatabase().getEntryByKey("Patterson06").get(), + result.getDatabase()); // Test whether we the main function can load the bibtex correctly BibEntry b = XMPUtil.readXMP(pdfFile).get(0); Assert.assertNotNull(b); - Assert.assertEquals(originalAuthors, AuthorList.parse(b.getField("author"))); + Assert.assertEquals(originalAuthors, AuthorList.parse(b.getFieldOptional("author").get())); // Next check from Document Information try (PDDocument document = PDDocument.load(pdfFile.getAbsoluteFile())) { @@ -1369,7 +1372,7 @@ public void testResolveStrings2() throws IOException, TransformerException { AuthorList.parse(document.getDocumentInformation().getAuthor())); b = XMPUtil.getBibtexEntryFromDocumentInformation(document.getDocumentInformation()).get(); - Assert.assertEquals(originalAuthors, AuthorList.parse(b.getField("author"))); + Assert.assertEquals(originalAuthors, AuthorList.parse(b.getFieldOptional("author").get())); // Now check from Dublin Core PDDocumentCatalog catalog = document.getDocumentCatalog(); @@ -1395,7 +1398,7 @@ public void testResolveStrings2() throws IOException, TransformerException { b = XMPUtil.getBibtexEntryFromDublinCore(dcSchema).get(); Assert.assertNotNull(b); - Assert.assertEquals(originalAuthors, AuthorList.parse(b.getField("author"))); + Assert.assertEquals(originalAuthors, AuthorList.parse(b.getFieldOptional("author").get())); } } finally { if (!pdfFile.delete()) { diff --git a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java index 4e450556373a..51a4770b7887 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java @@ -43,7 +43,7 @@ public void testDefaultConstructor() { // we have to use `getType("misc")` in the case of biblatex mode Assert.assertEquals("misc", entry.getType()); Assert.assertNotNull(entry.getId()); - Assert.assertNull(entry.getField("author")); + Assert.assertFalse(entry.getFieldOptional("author").isPresent()); } @Test @@ -145,63 +145,63 @@ public void testGetPublicationDate() { public void getFieldOrAliasDateWithYearNumericalMonthString() { emptyEntry.setField("year", "2003"); emptyEntry.setField("month", "3"); - Assert.assertEquals("2003-03", emptyEntry.getFieldOrAlias("date")); + Assert.assertEquals(Optional.of("2003-03"), emptyEntry.getFieldOrAlias("date")); } @Test public void getFieldOrAliasDateWithYearAbbreviatedMonth() { emptyEntry.setField("year", "2003"); emptyEntry.setField("month", "#mar#"); - Assert.assertEquals("2003-03", emptyEntry.getFieldOrAlias("date")); + Assert.assertEquals(Optional.of("2003-03"), emptyEntry.getFieldOrAlias("date")); } @Test public void getFieldOrAliasDateWithYearAbbreviatedMonthString() { emptyEntry.setField("year", "2003"); emptyEntry.setField("month", "mar"); - Assert.assertEquals("2003-03", emptyEntry.getFieldOrAlias("date")); + Assert.assertEquals(Optional.of("2003-03"), emptyEntry.getFieldOrAlias("date")); } @Test public void getFieldOrAliasDateWithOnlyYear() { emptyEntry.setField("year", "2003"); - Assert.assertEquals("2003", emptyEntry.getFieldOrAlias("date")); + Assert.assertEquals(Optional.of("2003"), emptyEntry.getFieldOrAlias("date")); } @Test public void getFieldOrAliasYearWithDateYYYY() { emptyEntry.setField("date", "2003"); - Assert.assertEquals("2003", emptyEntry.getFieldOrAlias("year")); + Assert.assertEquals(Optional.of("2003"), emptyEntry.getFieldOrAlias("year")); } @Test public void getFieldOrAliasYearWithDateYYYYMM() { emptyEntry.setField("date", "2003-03"); - Assert.assertEquals("2003", emptyEntry.getFieldOrAlias("year")); + Assert.assertEquals(Optional.of("2003"), emptyEntry.getFieldOrAlias("year")); } @Test public void getFieldOrAliasYearWithDateYYYYMMDD() { emptyEntry.setField("date", "2003-03-30"); - Assert.assertEquals("2003", emptyEntry.getFieldOrAlias("year")); + Assert.assertEquals(Optional.of("2003"), emptyEntry.getFieldOrAlias("year")); } @Test public void getFieldOrAliasMonthWithDateYYYYReturnsNull() { emptyEntry.setField("date", "2003"); - Assert.assertNull(emptyEntry.getFieldOrAlias("month")); + Assert.assertEquals(Optional.empty(), emptyEntry.getFieldOrAlias("month")); } @Test public void getFieldOrAliasMonthWithDateYYYYMM() { emptyEntry.setField("date", "2003-03"); - Assert.assertEquals("3", emptyEntry.getFieldOrAlias("month")); + Assert.assertEquals(Optional.of("3"), emptyEntry.getFieldOrAlias("month")); } @Test public void getFieldOrAliasMonthWithDateYYYYMMDD() { emptyEntry.setField("date", "2003-03-30"); - Assert.assertEquals("3", emptyEntry.getFieldOrAlias("month")); + Assert.assertEquals(Optional.of("3"), emptyEntry.getFieldOrAlias("month")); } @Test(expected = NullPointerException.class) @@ -382,9 +382,9 @@ public void testCiteKeyAndID() { be.setCiteKey("Einstein1931"); Assert.assertTrue(be.hasCiteKey()); Assert.assertEquals("Einstein1931", be.getCiteKey()); - Assert.assertEquals("Albert Einstein", be.getField("author")); + Assert.assertEquals(Optional.of("Albert Einstein"), be.getFieldOptional("author")); be.clearField("author"); - Assert.assertNull(be.getField("author")); + Assert.assertEquals(Optional.empty(), be.getFieldOptional("author")); String id = IdGenerator.next(); be.setId(id); From c2810c8e2211b2f53964f8f3bd32a51f57dbb4e9 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Wed, 13 Jul 2016 10:17:01 +0200 Subject: [PATCH 216/268] Fix compilation. --- .../net/sf/jabref/gui/entryeditor/FieldExtraComponents.java | 3 ++- .../sf/jabref/gui/maintable/MainTableSelectionListener.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index b6040c411061..cf6d4e7215cc 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -486,7 +486,8 @@ public static Optional getCrossrefExtraComponent(FieldEditor fieldEd JTextComponent crossref = (JTextComponent) fieldEditor; button.addActionListener( - actionEvent -> panel.highlightEntry(panel.getDatabase().getEntryByKey(crossref.getText()))); + actionEvent -> panel.getDatabase().getEntryByKey(crossref.getText()).ifPresent(e -> panel.highlightEntry(e)) + ); // enable/disable button crossref.getDocument().addDocumentListener(new DocumentListener() { diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index 0e130c13d748..27ceed50cfa5 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -338,7 +338,7 @@ public void mouseClicked(MouseEvent e) { }); } else if (modelColumn.getBibtexFields().contains("crossref")) { // Clicking on crossref column tableRows.get(row).getFieldOptional("crossref") - .ifPresent(crossref -> panel.highlightEntry(panel.getDatabase().getEntryByKey(crossref))); + .ifPresent(crossref -> panel.getDatabase().getEntryByKey(crossref).ifPresent(entry -> panel.highlightEntry(entry))); } } From 7eb19241b92c7984f9b5db64e9fee40615c81dcd Mon Sep 17 00:00:00 2001 From: matthiasgeiger Date: Wed, 13 Jul 2016 10:31:02 +0200 Subject: [PATCH 217/268] add GitHub icon to toolbar --- src/main/java/net/sf/jabref/gui/JabRefFrame.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 0a6cd4addefa..6b43f4ef2962 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -1477,6 +1477,7 @@ private void createToolBar() { tlb.add(pushExternalButton.getComponent()); tlb.addSeparator(); tlb.add(donationAction); + tlb.add(forkMeOnGitHubAction); } /** From 638ec99017e507d974d237d221f9b438b360fd22 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 13 Jul 2016 11:02:34 +0200 Subject: [PATCH 218/268] Typo fixed --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57e789922fe5..ac4c9505fea9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed -- Implemented [#661](https://github.com/JabRef/jabref/issues/661): Introducing a "check for updates" mechnism (manually/automatic at startup) +- Implemented [#661](https://github.com/JabRef/jabref/issues/661): Introducing a "check for updates" mechanism (manually/automatic at startup) - [#1485](https://github.com/JabRef/jabref/issues/1485): Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography - [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view - Updated German translation From 304d2802162a7e75edda5fbc893666cc73efe669 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 13 Jul 2016 11:38:45 +0200 Subject: [PATCH 219/268] Fix #1500: Renaming of explicit groups changes entries accordingly (#1539) * Fix #1500: Renaming of explicit groups changes entries accordingly * Add changelog entry * Hide GroupTreeNode constructor behind static method * Rename fields * Rename variables in GroupDialog * Change Util to WarnAssignmentSideEffects --- CHANGELOG.md | 1 + .../sf/jabref/gui/groups/AutoGroupDialog.java | 4 +- .../net/sf/jabref/gui/groups/GroupDialog.java | 315 +++++++----------- .../sf/jabref/gui/groups/GroupSelector.java | 28 +- .../gui/groups/GroupTreeNodeViewModel.java | 2 +- .../gui/groups/UndoableAddOrRemoveGroup.java | 2 +- .../sf/jabref/logic/groups/GroupTreeNode.java | 45 ++- .../sf/jabref/logic/groups/GroupsParser.java | 2 +- .../jabref/sql/importer/DatabaseImporter.java | 4 +- .../exporter/BibDatabaseWriterTest.java | 6 +- .../ConvertLegacyExplicitGroupsTest.java | 8 +- .../logic/groups/GroupTreeNodeTest.java | 97 +++++- .../jabref/sql/DatabaseImportExportTests.java | 2 +- 13 files changed, 287 insertions(+), 229 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac4c9505fea9..56deb7c0b955 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1507](https://github.com/JabRef/jabref/issues/1507): Keywords are now separated by the delimiter specified in the preferences - Fixed [#1484](https://github.com/JabRef/jabref/issues/1484): HTML export handles some UTF characters wrong - Fixed [#1534](https://github.com/JabRef/jabref/issues/1534): "Mark entries imported into database" does not work correctly +- Fixed [#1500](https://github.com/JabRef/jabref/issues/1500): Renaming of explicit groups now changes entries accordingly - Fixed issue where field changes were not undoable if the time stamp was updated on editing ### Removed diff --git a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java index 808a2f0b02cd..335f1470d106 100644 --- a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java @@ -93,7 +93,7 @@ public void actionPerformed(ActionEvent e) { dispose(); try { - GroupTreeNode autoGroupsRoot = new GroupTreeNode( + GroupTreeNode autoGroupsRoot = GroupTreeNode.fromGroup( new ExplicitGroup(Localization.lang("Automatically created groups"), GroupHierarchyType.INCLUDING)); Set hs; String fieldText = field.getText(); @@ -121,7 +121,7 @@ public void actionPerformed(ActionEvent e) { for (String keyword : hs) { KeywordGroup group = new KeywordGroup(keyword, fieldText, keyword, false, false, GroupHierarchyType.INDEPENDENT); - autoGroupsRoot.addChild(new GroupTreeNode(group)); + autoGroupsRoot.addChild(GroupTreeNode.fromGroup(group)); } autoGroupsRoot.moveTo(m_groupsRoot.getNode()); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index ff788415f47c..37d8f9847d30 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -22,9 +22,6 @@ import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ItemListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -37,7 +34,6 @@ import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; -import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; @@ -45,7 +41,6 @@ import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import javax.swing.event.CaretListener; -import javax.swing.undo.AbstractUndoableEdit; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; @@ -56,7 +51,6 @@ import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.groups.AbstractGroup; -import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.groups.ExplicitGroup; import net.sf.jabref.logic.groups.GroupHierarchyType; import net.sf.jabref.logic.groups.KeywordGroup; @@ -64,7 +58,6 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.strings.StringUtil; -import net.sf.jabref.model.entry.BibEntry; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.DefaultFormBuilder; @@ -76,37 +69,37 @@ */ class GroupDialog extends JDialog { - private static final int INDEX_EXPLICITGROUP = 0; - private static final int INDEX_KEYWORDGROUP = 1; - private static final int INDEX_SEARCHGROUP = 2; + private static final int INDEX_EXPLICIT_GROUP = 0; + private static final int INDEX_KEYWORD_GROUP = 1; + private static final int INDEX_SEARCH_GROUP = 2; private static final int TEXTFIELD_LENGTH = 30; // for all types - private final JTextField m_name = new JTextField(GroupDialog.TEXTFIELD_LENGTH); - private final JRadioButton m_explicitRadioButton = new JRadioButton( + private final JTextField nameField = new JTextField(GroupDialog.TEXTFIELD_LENGTH); + private final JRadioButton explicitRadioButton = new JRadioButton( Localization.lang("Statically group entries by manual assignment")); - private final JRadioButton m_keywordsRadioButton = new JRadioButton( + private final JRadioButton keywordsRadioButton = new JRadioButton( Localization.lang("Dynamically group entries by searching a field for a keyword")); - private final JRadioButton m_searchRadioButton = new JRadioButton( + private final JRadioButton searchRadioButton = new JRadioButton( Localization.lang("Dynamically group entries by a free-form search expression")); - private final JRadioButton m_independentButton = new JRadioButton( + private final JRadioButton independentButton = new JRadioButton( Localization.lang("Independent group: When selected, view only this group's entries")); - private final JRadioButton m_intersectionButton = new JRadioButton( + private final JRadioButton intersectionButton = new JRadioButton( Localization.lang("Refine supergroup: When selected, view entries contained in both this group and its supergroup")); - private final JRadioButton m_unionButton = new JRadioButton( + private final JRadioButton unionButton = new JRadioButton( Localization.lang("Include subgroups: When selected, view entries contained in this group or its subgroups")); // for KeywordGroup - private final JTextField m_kgSearchField = new JTextField(GroupDialog.TEXTFIELD_LENGTH); - private final TextField m_kgSearchTerm = new TextField("keywords", "", false); - private final JCheckBox m_kgCaseSensitive = new JCheckBox(Localization.lang("Case sensitive")); - private final JCheckBox m_kgRegExp = new JCheckBox(Localization.lang("regular expression")); + private final JTextField keywordGroupSearchField = new JTextField(GroupDialog.TEXTFIELD_LENGTH); + private final TextField keywordGroupSearchTerm = new TextField("keywords", "", false); + private final JCheckBox keywordGroupCaseSensitive = new JCheckBox(Localization.lang("Case sensitive")); + private final JCheckBox keywordGroupRegExp = new JCheckBox(Localization.lang("regular expression")); // for SearchGroup - private final JTextField m_sgSearchExpression = new JTextField(GroupDialog.TEXTFIELD_LENGTH); - private final JCheckBox m_sgCaseSensitive = new JCheckBox(Localization.lang("Case sensitive")); - private final JCheckBox m_sgRegExp = new JCheckBox(Localization.lang("regular expression")); + private final JTextField searchGroupSearchExpression = new JTextField(GroupDialog.TEXTFIELD_LENGTH); + private final JCheckBox searchGroupCaseSensitive = new JCheckBox(Localization.lang("Case sensitive")); + private final JCheckBox searchGroupRegExp = new JCheckBox(Localization.lang("regular expression")); // for all types - private final JButton m_ok = new JButton(Localization.lang("OK")); - private final JPanel m_optionsPanel = new JPanel(); - private final JLabel m_description = new JLabel() { + private final JButton okButton = new JButton(Localization.lang("OK")); + private final JPanel optionsPanel = new JPanel(); + private final JLabel descriptionLabel = new JLabel() { @Override public Dimension getPreferredSize() { @@ -118,17 +111,11 @@ public Dimension getPreferredSize() { } }; - private boolean mOkPressed; + private boolean isOkPressed; - private final BasePanel m_basePanel; + private AbstractGroup resultingGroup; - private AbstractGroup mResultingGroup; - - private AbstractUndoableEdit mUndoAddPreviousEntires; - - private final AbstractGroup m_editedGroup; - - private final CardLayout m_optionsLayout = new CardLayout(); + private final CardLayout optionsLayout = new CardLayout(); /** * Shows a group add/edit dialog. @@ -141,60 +128,57 @@ public Dimension getPreferredSize() { public GroupDialog(JabRefFrame jabrefFrame, BasePanel basePanel, AbstractGroup editedGroup) { super(jabrefFrame, Localization.lang("Edit group"), true); - m_basePanel = basePanel; - m_editedGroup = editedGroup; // set default values (overwritten if editedGroup != null) - m_kgSearchField.setText(jabrefFrame.prefs().get(JabRefPreferences.GROUPS_DEFAULT_FIELD)); + keywordGroupSearchField.setText(jabrefFrame.prefs().get(JabRefPreferences.GROUPS_DEFAULT_FIELD)); // configure elements ButtonGroup groupType = new ButtonGroup(); - groupType.add(m_explicitRadioButton); - groupType.add(m_keywordsRadioButton); - groupType.add(m_searchRadioButton); + groupType.add(explicitRadioButton); + groupType.add(keywordsRadioButton); + groupType.add(searchRadioButton); ButtonGroup groupHierarchy = new ButtonGroup(); - groupHierarchy.add(m_independentButton); - groupHierarchy.add(m_intersectionButton); - groupHierarchy.add(m_unionButton); - m_description.setVerticalAlignment(SwingConstants.TOP); - getRootPane().setDefaultButton(m_ok); + groupHierarchy.add(independentButton); + groupHierarchy.add(intersectionButton); + groupHierarchy.add(unionButton); + descriptionLabel.setVerticalAlignment(SwingConstants.TOP); + getRootPane().setDefaultButton(okButton); // build individual layout cards for each group - m_optionsPanel.setLayout(m_optionsLayout); + optionsPanel.setLayout(optionsLayout); // ... for explicit group - m_optionsPanel.add(new JPanel(), String.valueOf(GroupDialog.INDEX_EXPLICITGROUP)); + optionsPanel.add(new JPanel(), String.valueOf(GroupDialog.INDEX_EXPLICIT_GROUP)); // ... for keyword group FormLayout layoutKG = new FormLayout( "right:pref, 4dlu, fill:1dlu:grow, 2dlu, left:pref"); DefaultFormBuilder builderKG = new DefaultFormBuilder(layoutKG); builderKG.append(Localization.lang("Field")); - builderKG.append(m_kgSearchField, 3); + builderKG.append(keywordGroupSearchField, 3); builderKG.nextLine(); builderKG.append(Localization.lang("Keyword")); - builderKG.append(m_kgSearchTerm); - builderKG.append(new FieldContentSelector(jabrefFrame, m_basePanel, this, - m_kgSearchTerm, null, true, ", ")); + builderKG.append(keywordGroupSearchTerm); + builderKG.append(new FieldContentSelector(jabrefFrame, basePanel, this, keywordGroupSearchTerm, null, true, ", ")); builderKG.nextLine(); - builderKG.append(m_kgCaseSensitive, 3); + builderKG.append(keywordGroupCaseSensitive, 3); builderKG.nextLine(); - builderKG.append(m_kgRegExp, 3); - m_optionsPanel.add(builderKG.getPanel(), String.valueOf(GroupDialog.INDEX_KEYWORDGROUP)); + builderKG.append(keywordGroupRegExp, 3); + optionsPanel.add(builderKG.getPanel(), String.valueOf(GroupDialog.INDEX_KEYWORD_GROUP)); // ... for search group FormLayout layoutSG = new FormLayout("right:pref, 4dlu, fill:1dlu:grow"); DefaultFormBuilder builderSG = new DefaultFormBuilder(layoutSG); builderSG.append(Localization.lang("Search expression")); - builderSG.append(m_sgSearchExpression); + builderSG.append(searchGroupSearchExpression); builderSG.nextLine(); - builderSG.append(m_sgCaseSensitive, 3); + builderSG.append(searchGroupCaseSensitive, 3); builderSG.nextLine(); - builderSG.append(m_sgRegExp, 3); - m_optionsPanel.add(builderSG.getPanel(), String.valueOf(GroupDialog.INDEX_SEARCHGROUP)); + builderSG.append(searchGroupRegExp, 3); + optionsPanel.add(builderSG.getPanel(), String.valueOf(GroupDialog.INDEX_SEARCH_GROUP)); // ... for buttons panel FormLayout layoutBP = new FormLayout("pref, 4dlu, pref", "p"); layoutBP.setColumnGroups(new int[][] {{1, 3}}); ButtonBarBuilder builderBP = new ButtonBarBuilder(); builderBP.addGlue(); - builderBP.addButton(m_ok); + builderBP.addButton(okButton); JButton mCancel = new JButton(Localization.lang("Cancel")); builderBP.addButton(mCancel); builderBP.addGlue(); @@ -212,40 +196,40 @@ public GroupDialog(JabRefFrame jabrefFrame, BasePanel basePanel, builderAll.nextLine(); builderAll.nextLine(); builderAll.append(Localization.lang("Name")); - builderAll.append(m_name); + builderAll.append(nameField); builderAll.nextLine(); builderAll.nextLine(); - builderAll.append(m_explicitRadioButton, 5); + builderAll.append(explicitRadioButton, 5); builderAll.nextLine(); builderAll.nextLine(); - builderAll.append(m_keywordsRadioButton, 5); + builderAll.append(keywordsRadioButton, 5); builderAll.nextLine(); builderAll.nextLine(); - builderAll.append(m_searchRadioButton, 5); + builderAll.append(searchRadioButton, 5); builderAll.nextLine(); builderAll.nextLine(); builderAll.appendSeparator(Localization.lang("Hierarchical context")); builderAll.nextLine(); builderAll.nextLine(); - builderAll.append(m_independentButton, 5); + builderAll.append(independentButton, 5); builderAll.nextLine(); builderAll.nextLine(); - builderAll.append(m_intersectionButton, 5); + builderAll.append(intersectionButton, 5); builderAll.nextLine(); builderAll.nextLine(); - builderAll.append(m_unionButton, 5); + builderAll.append(unionButton, 5); builderAll.nextLine(); builderAll.nextLine(); builderAll.appendSeparator(Localization.lang("Options")); builderAll.nextLine(); builderAll.nextLine(); - builderAll.append(m_optionsPanel, 5); + builderAll.append(optionsPanel, 5); builderAll.nextLine(); builderAll.nextLine(); builderAll.appendSeparator(Localization.lang("Description")); builderAll.nextLine(); builderAll.nextLine(); - JScrollPane sp = new JScrollPane(m_description, + JScrollPane sp = new JScrollPane(descriptionLabel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED) { @@ -275,9 +259,9 @@ public Dimension getPreferredSize() { setLayoutForSelectedGroup(); updateComponents(); }; - m_explicitRadioButton.addItemListener(radioButtonItemListener); - m_keywordsRadioButton.addItemListener(radioButtonItemListener); - m_searchRadioButton.addItemListener(radioButtonItemListener); + explicitRadioButton.addItemListener(radioButtonItemListener); + keywordsRadioButton.addItemListener(radioButtonItemListener); + searchRadioButton.addItemListener(radioButtonItemListener); Action cancelAction = new AbstractAction() { @@ -291,37 +275,24 @@ public void actionPerformed(ActionEvent e) { .put(Globals.getKeyPrefs().getKey(KeyBinding.CLOSE_DIALOG), "close"); builderAll.getPanel().getActionMap().put("close", cancelAction); - m_ok.addActionListener(e -> { - mOkPressed = true; + okButton.addActionListener(e -> { + isOkPressed = true; try { - if (m_explicitRadioButton.isSelected()) { - if (m_editedGroup instanceof ExplicitGroup) { - // keep assignments from possible previous ExplicitGroup - mResultingGroup = m_editedGroup.deepCopy(); - mResultingGroup.setName(m_name.getText().trim()); - mResultingGroup.setHierarchicalContext(getContext()); - } else { - mResultingGroup = new ExplicitGroup(m_name.getText().trim(), getContext()); - if (m_editedGroup != null) { - addPreviousEntries(); - } - } - } else if (m_keywordsRadioButton.isSelected()) { + if (explicitRadioButton.isSelected()) { + resultingGroup = new ExplicitGroup(nameField.getText().trim(), getContext()); + } else if (keywordsRadioButton.isSelected()) { // regex is correct, otherwise OK would have been disabled // therefore I don't catch anything here - mResultingGroup = new KeywordGroup(m_name.getText().trim(), m_kgSearchField.getText().trim(), - m_kgSearchTerm.getText().trim(), m_kgCaseSensitive.isSelected(), m_kgRegExp.isSelected(), + resultingGroup = new KeywordGroup(nameField.getText().trim(), keywordGroupSearchField.getText().trim(), + keywordGroupSearchTerm.getText().trim(), keywordGroupCaseSensitive.isSelected(), keywordGroupRegExp + .isSelected(), getContext()); - if (((m_editedGroup instanceof ExplicitGroup) || (m_editedGroup instanceof SearchGroup)) - && mResultingGroup.supportsAdd()) { - addPreviousEntries(); - } - } else if (m_searchRadioButton.isSelected()) { + } else if (searchRadioButton.isSelected()) { try { // regex is correct, otherwise OK would have been // disabled // therefore I don't catch anything here - mResultingGroup = new SearchGroup(m_name.getText().trim(), m_sgSearchExpression.getText().trim(), + resultingGroup = new SearchGroup(nameField.getText().trim(), searchGroupSearchExpression.getText().trim(), isCaseSensitive(), isRegex(), getContext()); } catch (Exception e1) { // should never happen @@ -336,97 +307,97 @@ public void actionPerformed(ActionEvent e) { CaretListener caretListener = e -> updateComponents(); ItemListener itemListener = e -> updateComponents(); - m_name.addCaretListener(caretListener); - m_kgSearchField.addCaretListener(caretListener); - m_kgSearchTerm.addCaretListener(caretListener); - m_kgCaseSensitive.addItemListener(itemListener); - m_kgRegExp.addItemListener(itemListener); - m_sgSearchExpression.addCaretListener(caretListener); - m_sgRegExp.addItemListener(itemListener); - m_sgCaseSensitive.addItemListener(itemListener); + nameField.addCaretListener(caretListener); + keywordGroupSearchField.addCaretListener(caretListener); + keywordGroupSearchTerm.addCaretListener(caretListener); + keywordGroupCaseSensitive.addItemListener(itemListener); + keywordGroupRegExp.addItemListener(itemListener); + searchGroupSearchExpression.addCaretListener(caretListener); + searchGroupRegExp.addItemListener(itemListener); + searchGroupCaseSensitive.addItemListener(itemListener); // configure for current type if (editedGroup != null && editedGroup.getClass() == KeywordGroup.class) { KeywordGroup group = (KeywordGroup) editedGroup; - m_name.setText(group.getName()); - m_kgSearchField.setText(group.getSearchField()); - m_kgSearchTerm.setText(group.getSearchExpression()); - m_kgCaseSensitive.setSelected(group.isCaseSensitive()); - m_kgRegExp.setSelected(group.isRegExp()); - m_keywordsRadioButton.setSelected(true); + nameField.setText(group.getName()); + keywordGroupSearchField.setText(group.getSearchField()); + keywordGroupSearchTerm.setText(group.getSearchExpression()); + keywordGroupCaseSensitive.setSelected(group.isCaseSensitive()); + keywordGroupRegExp.setSelected(group.isRegExp()); + keywordsRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); } else if (editedGroup != null && editedGroup.getClass() == SearchGroup.class) { SearchGroup group = (SearchGroup) editedGroup; - m_name.setText(group.getName()); - m_sgSearchExpression.setText(group.getSearchExpression()); - m_sgCaseSensitive.setSelected(group.isCaseSensitive()); - m_sgRegExp.setSelected(group.isRegExp()); - m_searchRadioButton.setSelected(true); + nameField.setText(group.getName()); + searchGroupSearchExpression.setText(group.getSearchExpression()); + searchGroupCaseSensitive.setSelected(group.isCaseSensitive()); + searchGroupRegExp.setSelected(group.isRegExp()); + searchRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); } else if (editedGroup != null && editedGroup.getClass() == ExplicitGroup.class) { - m_name.setText(editedGroup.getName()); - m_explicitRadioButton.setSelected(true); + nameField.setText(editedGroup.getName()); + explicitRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); } else { // creating new group -> defaults! - m_explicitRadioButton.setSelected(true); + explicitRadioButton.setSelected(true); setContext(GroupHierarchyType.INDEPENDENT); } } public boolean okPressed() { - return mOkPressed; + return isOkPressed; } public AbstractGroup getResultingGroup() { - return mResultingGroup; + return resultingGroup; } private void setLayoutForSelectedGroup() { - if (m_explicitRadioButton.isSelected()) { - m_optionsLayout.show(m_optionsPanel, String.valueOf(GroupDialog.INDEX_EXPLICITGROUP)); - } else if (m_keywordsRadioButton.isSelected()) { - m_optionsLayout.show(m_optionsPanel, String.valueOf(GroupDialog.INDEX_KEYWORDGROUP)); - } else if (m_searchRadioButton.isSelected()) { - m_optionsLayout.show(m_optionsPanel, String.valueOf(GroupDialog.INDEX_SEARCHGROUP)); + if (explicitRadioButton.isSelected()) { + optionsLayout.show(optionsPanel, String.valueOf(GroupDialog.INDEX_EXPLICIT_GROUP)); + } else if (keywordsRadioButton.isSelected()) { + optionsLayout.show(optionsPanel, String.valueOf(GroupDialog.INDEX_KEYWORD_GROUP)); + } else if (searchRadioButton.isSelected()) { + optionsLayout.show(optionsPanel, String.valueOf(GroupDialog.INDEX_SEARCH_GROUP)); } } private void updateComponents() { // all groups need a name - boolean okEnabled = !m_name.getText().trim().isEmpty(); + boolean okEnabled = !nameField.getText().trim().isEmpty(); if (!okEnabled) { setDescription(Localization.lang("Please enter a name for the group.")); - m_ok.setEnabled(false); + okButton.setEnabled(false); return; } String s1; String s2; - if (m_keywordsRadioButton.isSelected()) { - s1 = m_kgSearchField.getText().trim(); + if (keywordsRadioButton.isSelected()) { + s1 = keywordGroupSearchField.getText().trim(); okEnabled = okEnabled && s1.matches("\\w+"); - s2 = m_kgSearchTerm.getText().trim(); + s2 = keywordGroupSearchTerm.getText().trim(); okEnabled = okEnabled && !s2.isEmpty(); if (okEnabled) { - if (m_kgRegExp.isSelected()) { + if (keywordGroupRegExp.isSelected()) { try { Pattern.compile(s2); - setDescription(KeywordGroup.getDescriptionForPreview(s1, s2, m_kgCaseSensitive.isSelected(), - m_kgRegExp.isSelected())); + setDescription(KeywordGroup.getDescriptionForPreview(s1, s2, keywordGroupCaseSensitive.isSelected(), + keywordGroupRegExp.isSelected())); } catch (PatternSyntaxException e) { okEnabled = false; setDescription(formatRegExException(s2, e)); } } else { - setDescription(KeywordGroup.getDescriptionForPreview(s1, s2, m_kgCaseSensitive.isSelected(), - m_kgRegExp.isSelected())); + setDescription(KeywordGroup.getDescriptionForPreview(s1, s2, keywordGroupCaseSensitive.isSelected(), + keywordGroupRegExp.isSelected())); } } else { setDescription(Localization.lang( "Please enter the field to search (e.g. keywords) and the keyword to search it for (e.g. electrical).")); } setNameFontItalic(true); - } else if (m_searchRadioButton.isSelected()) { - s1 = m_sgSearchExpression.getText().trim(); + } else if (searchRadioButton.isSelected()) { + s1 = searchGroupSearchExpression.getText().trim(); okEnabled = okEnabled & !s1.isEmpty(); if (okEnabled) { setDescription(new SearchQuery(s1, isCaseSensitive(), isRegex()).getDescription()); @@ -447,57 +418,23 @@ private void updateComponents() { + "author=smith and title=electrical")); } setNameFontItalic(true); - } else if (m_explicitRadioButton.isSelected()) { + } else if (explicitRadioButton.isSelected()) { setDescription(ExplicitGroup.getDescriptionForPreview()); setNameFontItalic(false); } - m_ok.setEnabled(okEnabled); + okButton.setEnabled(okEnabled); } private boolean isRegex() { - return m_sgRegExp.isSelected(); + return searchGroupRegExp.isSelected(); } private boolean isCaseSensitive() { - return m_sgCaseSensitive.isSelected(); - } - - /** - * This is used when a group is converted and the new group supports - * explicit adding of entries: All entries that match the previous group are - * added to the new group. - */ - private void addPreviousEntries() { - int i = JOptionPane.showConfirmDialog(m_basePanel.frame(), - Localization.lang("Assign the original group's entries to this group?"), - Localization.lang("Change of Grouping Method"), - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (i == JOptionPane.NO_OPTION) { - return; - } - List list = new ArrayList<>(); - for (BibEntry entry : m_basePanel.getDatabase().getEntries()) { - if (m_editedGroup.contains(entry)) { - list.add(entry); - } - } - if (!list.isEmpty()) { - if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(mResultingGroup, this)) { - return; - } - // the undo information for a conversion to an ExplicitGroup is - // contained completely in the UndoableModifyGroup object. - if (!(mResultingGroup instanceof ExplicitGroup) && mResultingGroup.supportsAdd()) { - Optional addChange = mResultingGroup.add(list); - if(addChange.isPresent()) { - mUndoAddPreviousEntires = UndoableChangeEntriesOfGroup.getUndoableEdit(null, addChange.get()); - } - } - } + return searchGroupCaseSensitive.isSelected(); } private void setDescription(String description) { - m_description.setText("" + description + ""); + descriptionLabel.setText("" + description + ""); } private static String formatRegExException(String regExp, Exception e) { @@ -526,22 +463,14 @@ private static String formatRegExException(String regExp, Exception e) { return s; } - /** - * Returns an undo object for adding the edited group's entries to the new - * group, or null if this did not occur. - */ - public AbstractUndoableEdit getUndoForAddPreviousEntries() { - return mUndoAddPreviousEntires; - } - /** * Sets the font of the name entry field. */ private void setNameFontItalic(boolean italic) { - Font f = m_name.getFont(); + Font f = nameField.getFont(); if (f.isItalic() != italic) { f = f.deriveFont(italic ? Font.ITALIC : Font.PLAIN); - m_name.setFont(f); + nameField.setFont(f); } } @@ -549,13 +478,13 @@ private void setNameFontItalic(boolean italic) { * Returns the int representing the selected hierarchical group context. */ private GroupHierarchyType getContext() { - if (m_independentButton.isSelected()) { + if (independentButton.isSelected()) { return GroupHierarchyType.INDEPENDENT; } - if (m_intersectionButton.isSelected()) { + if (intersectionButton.isSelected()) { return GroupHierarchyType.REFINING; } - if (m_unionButton.isSelected()) { + if (unionButton.isSelected()) { return GroupHierarchyType.INCLUDING; } return GroupHierarchyType.INDEPENDENT; // default @@ -563,11 +492,11 @@ private GroupHierarchyType getContext() { private void setContext(GroupHierarchyType context) { if (context == GroupHierarchyType.REFINING) { - m_intersectionButton.setSelected(true); + intersectionButton.setSelected(true); } else if (context == GroupHierarchyType.INCLUDING) { - m_unionButton.setSelected(true); + unionButton.setSelected(true); } else { - m_independentButton.setSelected(true); + independentButton.setSelected(true); } } } diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 715001ef3a66..8780d9aa6434 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -72,6 +72,7 @@ import net.sf.jabref.gui.worker.AbstractWorker; import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.AllEntriesGroup; +import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.groups.MoveGroupChange; import net.sf.jabref.logic.l10n.Localization; @@ -353,7 +354,7 @@ public void stateChanged(ChangeEvent e) { KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.CTRL_MASK)); - setGroups(new GroupTreeNode(new AllEntriesGroup())); + setGroups(GroupTreeNode.fromGroup(new AllEntriesGroup())); } private void definePopup() { @@ -787,10 +788,25 @@ public void actionPerformed(ActionEvent e) { gd.setVisible(true); if (gd.okPressed()) { AbstractGroup newGroup = gd.getResultingGroup(); - AbstractUndoableEdit undoAddPreviousEntries = gd.getUndoForAddPreviousEntries(); + + int i = JOptionPane.showConfirmDialog(panel.frame(), + Localization.lang("Assign the original group's entries to this group?"), + Localization.lang("Change of Grouping Method"), + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + boolean keepPreviousAssignments = i == JOptionPane.YES_OPTION && + WarnAssignmentSideEffects.warnAssignmentSideEffects(newGroup, panel.frame()); + + AbstractUndoableEdit undoAddPreviousEntries = null; UndoableModifyGroup undo = new UndoableModifyGroup(GroupSelector.this, groupsRoot, node, newGroup); - node.getNode().setGroup(newGroup); + Optional addChange = node.getNode().setGroup(newGroup, keepPreviousAssignments, + panel.getDatabase().getEntries()); + if (addChange.isPresent()) { + undoAddPreviousEntries = UndoableChangeEntriesOfGroup.getUndoableEdit(null, addChange.get()); + } + + groupsTreeModel.reload(); revalidateGroups(node); + // Store undo information. if (undoAddPreviousEntries == null) { panel.getUndoManager().addEdit(undo); @@ -821,7 +837,7 @@ public void actionPerformed(ActionEvent e) { return; // ignore } final AbstractGroup newGroup = gd.getResultingGroup(); - final GroupTreeNode newNode = new GroupTreeNode(newGroup); + final GroupTreeNode newNode = GroupTreeNode.fromGroup(newGroup); final GroupTreeNodeViewModel node = getNodeToUse(); if (node == null) { groupsRoot.getNode().addChild(newNode); @@ -852,7 +868,7 @@ public void actionPerformed(ActionEvent e) { return; // ignore } final AbstractGroup newGroup = gd.getResultingGroup(); - final GroupTreeNode newNode = new GroupTreeNode(newGroup); + final GroupTreeNode newNode = GroupTreeNode.fromGroup(newGroup); final GroupTreeNodeViewModel node = getNodeToUse(); node.getNode().addChild(newNode); UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(groupsRoot, @@ -1202,7 +1218,7 @@ public void setActiveBasePanel(BasePanel panel) { } MetaData metaData = panel.getBibDatabaseContext().getMetaData(); if (metaData.getGroups() == null) { - GroupTreeNode newGroupsRoot = new GroupTreeNode(new AllEntriesGroup()); + GroupTreeNode newGroupsRoot = GroupTreeNode.fromGroup(new AllEntriesGroup()); metaData.setGroups(newGroupsRoot); setGroups(newGroupsRoot); } else { diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java index 8c0c91e4cc00..74435a804926 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -333,7 +333,7 @@ public boolean isAllEntriesGroup() { } public void addNewGroup(AbstractGroup newGroup, CountingUndoManager undoManager) { - GroupTreeNode newNode = new GroupTreeNode(newGroup); + GroupTreeNode newNode = GroupTreeNode.fromGroup(newGroup); this.getNode().addChild(newNode); UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(this, diff --git a/src/main/java/net/sf/jabref/gui/groups/UndoableAddOrRemoveGroup.java b/src/main/java/net/sf/jabref/gui/groups/UndoableAddOrRemoveGroup.java index 63803a68cd39..61c75b693f14 100644 --- a/src/main/java/net/sf/jabref/gui/groups/UndoableAddOrRemoveGroup.java +++ b/src/main/java/net/sf/jabref/gui/groups/UndoableAddOrRemoveGroup.java @@ -71,7 +71,7 @@ public UndoableAddOrRemoveGroup(GroupTreeNodeViewModel groupsRoot, // storing a backup of the whole subtree is not required when children // are kept m_subtreeBackup = editType != UndoableAddOrRemoveGroup.REMOVE_NODE_KEEP_CHILDREN ? editedNode.getNode() - .copySubtree() : new GroupTreeNode(editedNode.getNode().getGroup().deepCopy()); + .copySubtree() : GroupTreeNode.fromGroup(editedNode.getNode().getGroup().deepCopy()); // remember path to edited node. this cannot be stored as a reference, // because the reference itself might change. the method below is more // robust. diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java index 93a30b85ec01..905b2ad6e158 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java @@ -18,6 +18,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.search.SearchMatcher; @@ -38,11 +40,15 @@ public class GroupTreeNode extends TreeNode { * * @param group the group underlying this node */ - public GroupTreeNode(AbstractGroup group) { + private GroupTreeNode(AbstractGroup group) { super(GroupTreeNode.class); setGroup(group); } + public static GroupTreeNode fromGroup(AbstractGroup group) { + return new GroupTreeNode(group); + } + /** * Returns the group underlying this node. * @@ -55,10 +61,37 @@ public AbstractGroup getGroup() { /** * Associates the specified group with this node. * - * @param group the new group (has to be non-null) + * @param newGroup the new group (has to be non-null) */ - public void setGroup(AbstractGroup group) { - this.group = Objects.requireNonNull(group); + @Deprecated // use other overload + public void setGroup(AbstractGroup newGroup) { + this.group = Objects.requireNonNull(newGroup); + } + + /** + * Associates the specified group with this node while also providing the possibility to modify previous matched + * entries so that they are now matched by the new group. + * + * @param newGroup the new group (has to be non-null) + * @param shouldKeepPreviousAssignments specifies whether previous matched entries should be carried over + * @param entriesInDatabase list of entries in the database + */ + public Optional setGroup(AbstractGroup newGroup, boolean shouldKeepPreviousAssignments, + List entriesInDatabase) { + AbstractGroup oldGroup = getGroup(); + setGroup(newGroup); + + // Keep assignments from previous group + if (shouldKeepPreviousAssignments && newGroup.supportsAdd()) { + List entriesMatchedByOldGroup = entriesInDatabase.stream().filter(oldGroup::isMatch) + .collect(Collectors.toList()); + if (oldGroup instanceof ExplicitGroup && newGroup instanceof ExplicitGroup) { + // Rename of explicit group, so remove old group assignment + oldGroup.remove(entriesMatchedByOldGroup); + } + return newGroup.add(entriesMatchedByOldGroup); + } + return Optional.empty(); } /** @@ -200,7 +233,7 @@ public String getName() { } public GroupTreeNode addSubgroup(AbstractGroup group) { - GroupTreeNode child = new GroupTreeNode(group); + GroupTreeNode child = GroupTreeNode.fromGroup(group); addChild(child); return child; } @@ -212,7 +245,7 @@ public String toString() { @Override public GroupTreeNode copyNode() { - return new GroupTreeNode(group); + return GroupTreeNode.fromGroup(group); } public static GroupTreeNode parse(List orderedData) throws ParseException { diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java b/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java index b19a3873365e..82aae0af35a1 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java @@ -43,7 +43,7 @@ public static GroupTreeNode importGroups(List orderedData) throws ParseE } int level = Integer.parseInt(string.substring(0, spaceIndex)); AbstractGroup group = AbstractGroup.fromString(string.substring(spaceIndex + 1)); - GroupTreeNode newNode = new GroupTreeNode(group); + GroupTreeNode newNode = GroupTreeNode.fromGroup(group); if (cursor == null) { // create new root cursor = newNode; diff --git a/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java b/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java index 3c7da777093c..34a5ac3382a1 100644 --- a/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java +++ b/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java @@ -212,7 +212,7 @@ private void importGroupsTree(MetaData metaData, Map entries, final String database_id) throws SQLException { Map groups = new HashMap<>(); LinkedHashMap parentIds = new LinkedHashMap<>(); - GroupTreeNode rootNode = new GroupTreeNode(new AllEntriesGroup()); + GroupTreeNode rootNode = GroupTreeNode.fromGroup(new AllEntriesGroup()); String query = SQLUtil.queryAllFromTable("groups WHERE database_id='" + database_id + "' ORDER BY groups_id"); try (Statement statement = conn.createStatement(); @@ -253,7 +253,7 @@ private void importGroupsTree(MetaData metaData, Map entries, } if (group != null) { - GroupTreeNode node = new GroupTreeNode(group); + GroupTreeNode node = GroupTreeNode.fromGroup(group); parentIds.put(node, rsGroups.getString("parent_id")); groups.put(rsGroups.getString("groups_id"), node); } diff --git a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java index bfaa1c0535bc..a737d33db304 100644 --- a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java @@ -196,7 +196,7 @@ public void writeMetadataAndEncoding() throws IOException { @Test public void writeGroups() throws IOException, ParseException { - GroupTreeNode groupRoot = new GroupTreeNode(new AllEntriesGroup()); + GroupTreeNode groupRoot = GroupTreeNode.fromGroup(new AllEntriesGroup()); groupRoot.addSubgroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING)); metaData.setGroups(groupRoot); @@ -215,8 +215,8 @@ public void writeGroups() throws IOException, ParseException { public void writeGroupsAndEncoding() throws IOException, ParseException { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); - GroupTreeNode groupRoot = new GroupTreeNode(new AllEntriesGroup()); - groupRoot.addChild(new GroupTreeNode(new ExplicitGroup("test", GroupHierarchyType.INCLUDING))); + GroupTreeNode groupRoot = GroupTreeNode.fromGroup(new AllEntriesGroup()); + groupRoot.addChild(GroupTreeNode.fromGroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING))); metaData.setGroups(groupRoot); databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); diff --git a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java index d7b9fbb851da..0665e71ce349 100644 --- a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java +++ b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java @@ -39,7 +39,7 @@ public void setUp() throws Exception { @Test public void performActionWritesGroupMembershipInEntry() throws Exception { - ParserResult parserResult = generateParserResult(entry, new GroupTreeNode(group)); + ParserResult parserResult = generateParserResult(entry, GroupTreeNode.fromGroup(group)); action.performAction(basePanel, parserResult); @@ -48,7 +48,7 @@ public void performActionWritesGroupMembershipInEntry() throws Exception { @Test public void performActionClearsLegacyKeys() throws Exception { - ParserResult parserResult = generateParserResult(entry, new GroupTreeNode(group)); + ParserResult parserResult = generateParserResult(entry, GroupTreeNode.fromGroup(group)); action.performAction(basePanel, parserResult); @@ -57,7 +57,7 @@ public void performActionClearsLegacyKeys() throws Exception { @Test public void performActionWritesGroupMembershipInEntryForComplexGroupTree() throws Exception { - GroupTreeNode root = new GroupTreeNode(new AllEntriesGroup()); + GroupTreeNode root = GroupTreeNode.fromGroup(new AllEntriesGroup()); root.addSubgroup(new ExplicitGroup("TestGroup2", GroupHierarchyType.INCLUDING)); root.addSubgroup(group); ParserResult parserResult = generateParserResult(entry, root); @@ -69,7 +69,7 @@ public void performActionWritesGroupMembershipInEntryForComplexGroupTree() throw @Test public void isActionNecessaryReturnsTrueIfGroupContainsLegacyKeys() throws Exception { - ParserResult parserResult = generateParserResult(entry, new GroupTreeNode(group)); + ParserResult parserResult = generateParserResult(entry, GroupTreeNode.fromGroup(group)); assertTrue(action.isActionNecessary(parserResult)); } diff --git a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java index e0e78c1f010d..8010eb44fccd 100644 --- a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java @@ -5,6 +5,8 @@ import java.util.Collections; import java.util.List; +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.search.matchers.AndMatcher; import net.sf.jabref.logic.search.matchers.OrMatcher; @@ -14,15 +16,23 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class GroupTreeNodeTest { private List entries = new ArrayList<>(); + private BibEntry entry; @Before public void setUp() throws Exception { + entries.clear(); + entry = new BibEntry(); + entries.add(entry); entries.add(new BibEntry().withField("author", "author1 and author2")); entries.add(new BibEntry().withField("author", "author1")); + + Globals.prefs = JabRefPreferences.getInstance(); } @@ -33,14 +43,14 @@ public void setUp() throws Exception { * A ExplicitParent, Independent (= parent) * B ExplicitNode, Refining (<-- this) */ - public GroupTreeNode getNodeInSimpleTree(GroupTreeNode root) throws ParseException { + private GroupTreeNode getNodeInSimpleTree(GroupTreeNode root) throws ParseException { root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING)); GroupTreeNode parent = root.addSubgroup(new ExplicitGroup("ExplicitParent", GroupHierarchyType.INDEPENDENT)); GroupTreeNode node = parent.addSubgroup(new ExplicitGroup("ExplicitNode", GroupHierarchyType.REFINING)); return node; } - public GroupTreeNode getNodeInSimpleTree() throws ParseException { + private GroupTreeNode getNodeInSimpleTree() throws ParseException { return getNodeInSimpleTree(getRoot()); } @@ -61,7 +71,7 @@ public GroupTreeNode getNodeInSimpleTree() throws ParseException { * B KeywordB * A KeywordA */ - public GroupTreeNode getNodeInComplexTree(GroupTreeNode root) throws ParseException { + private GroupTreeNode getNodeInComplexTree(GroupTreeNode root) throws ParseException { root.addSubgroup(getSearchGroup("SearchA")); root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING)); GroupTreeNode grandParent = root.addSubgroup(new ExplicitGroup("ExplicitGrandParent", GroupHierarchyType.INDEPENDENT)); @@ -117,9 +127,8 @@ public GroupTreeNode getNodeAsChild(TreeNodeMock root) { return node; } */ - - public GroupTreeNode getRoot() { - return new GroupTreeNode(new AllEntriesGroup()); + private GroupTreeNode getRoot() { + return GroupTreeNode.fromGroup(new AllEntriesGroup()); } @Test @@ -162,13 +171,13 @@ public void getTreeAsStringInComplexTree() throws Exception { @Test public void getSearchRuleForIndependentGroupReturnsGroupAsMatcher() throws ParseException { - GroupTreeNode node = new GroupTreeNode(new ExplicitGroup("node", GroupHierarchyType.INDEPENDENT)); + GroupTreeNode node = GroupTreeNode.fromGroup(new ExplicitGroup("node", GroupHierarchyType.INDEPENDENT)); assertEquals(node.getGroup(), node.getSearchRule()); } @Test public void getSearchRuleForRefiningGroupReturnsParentAndGroupAsMatcher() throws ParseException { - GroupTreeNode parent = new GroupTreeNode(new ExplicitGroup("parent", GroupHierarchyType.INDEPENDENT)); + GroupTreeNode parent = GroupTreeNode.fromGroup(new ExplicitGroup("parent", GroupHierarchyType.INDEPENDENT)); GroupTreeNode node = parent.addSubgroup(new ExplicitGroup("node", GroupHierarchyType.REFINING)); AndMatcher matcher = new AndMatcher(); @@ -179,7 +188,7 @@ public void getSearchRuleForRefiningGroupReturnsParentAndGroupAsMatcher() throws @Test public void getSearchRuleForIncludingGroupReturnsGroupOrSubgroupAsMatcher() throws ParseException { - GroupTreeNode node = new GroupTreeNode(new ExplicitGroup("node", GroupHierarchyType.INCLUDING)); + GroupTreeNode node = GroupTreeNode.fromGroup(new ExplicitGroup("node", GroupHierarchyType.INCLUDING)); GroupTreeNode child = node.addSubgroup(new ExplicitGroup("child", GroupHierarchyType.INDEPENDENT)); OrMatcher matcher = new OrMatcher(); @@ -228,4 +237,74 @@ public void numberOfHitsWorksForHierarchyOfIndependentGroups() throws Exception new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.INDEPENDENT)); assertEquals(2, node.numberOfHits(entries)); } + + @Test + public void setGroupChangesUnderlyingGroup() throws Exception { + GroupTreeNode node = getNodeInSimpleTree(); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + + node.setGroup(newGroup, true, entries); + + assertEquals(newGroup, node.getGroup()); + } + + @Test + public void setGroupAddsPreviousAssignmentsExplicitToExplicit() throws Exception { + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + oldGroup.add(entry); + GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + + node.setGroup(newGroup, true, entries); + + assertTrue(newGroup.isMatch(entry)); + } + + @Test + public void setGroupWithFalseDoesNotAddsPreviousAssignments() throws Exception { + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + oldGroup.add(entry); + GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + + node.setGroup(newGroup, false, entries); + + assertFalse(newGroup.isMatch(entry)); + } + + @Test + public void setGroupAddsOnlyPreviousAssignments() throws Exception { + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + assertFalse(oldGroup.isMatch(entry)); + GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + + node.setGroup(newGroup, true, entries); + + assertFalse(newGroup.isMatch(entry)); + } + + @Test + public void setGroupExplicitToSearchDoesNotKeepPreviousAssignments() throws Exception { + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + oldGroup.add(entry); + GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); + AbstractGroup newGroup = new SearchGroup("NewGroup", "test", false, false, GroupHierarchyType.INDEPENDENT); + + node.setGroup(newGroup, true, entries); + + assertFalse(newGroup.isMatch(entry)); + } + + @Test + public void setGroupExplicitToExplicitIsRenameAndSoRemovesPreviousAssignment() throws Exception { + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + oldGroup.add(entry); + GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + + node.setGroup(newGroup, true, entries); + + assertFalse(oldGroup.isMatch(entry)); + } } diff --git a/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java b/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java index 0b30d09f5998..bab7c73d1a8a 100644 --- a/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java +++ b/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java @@ -178,7 +178,7 @@ private BibDatabaseContext createContextWithSingleEntryUsingQuoteSymbol() { private BibDatabaseContext createContextWithSingleEntrySingleGroup() throws ParseException { BibDatabaseContext databaseContext = createContextWithSingleEntry(); - GroupTreeNode root = new GroupTreeNode(new AllEntriesGroup()); + GroupTreeNode root = GroupTreeNode.fromGroup(new AllEntriesGroup()); KeywordGroup group = new KeywordGroup("test", "asdf", "fdas", false, true, GroupHierarchyType.INCLUDING); root.addSubgroup(group); databaseContext.getMetaData().setGroups(root); From c32a3a16d39248a7feec647fd586bcd3681886e1 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 13 Jul 2016 12:35:22 +0200 Subject: [PATCH 220/268] Fix typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7fefc2013be9..ea04a5cc7bfa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,7 +41,7 @@ More information on this can be found via `man git-shortlog`. ### Modify the header -The headers of each `.java` file states "JabREf contributors". +The headers of each `.java` file states "JabRef contributors". Author credits are given using the `AUTHORS` file and by using the `git blame` functionality. For instance, From 1f1c7df68333c9630742b57b7ab12af016a2ec50 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 13 Jul 2016 16:12:16 +0200 Subject: [PATCH 221/268] Fix #1490 Clean registry on uninstall --- jabref.install4j | 78 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/jabref.install4j b/jabref.install4j index d1bc2f25767a..a6bc97630258 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -116,7 +116,16 @@ - + + + + + + + + + + @@ -148,14 +157,6 @@ context.getBooleanVariable("sys.confirmedUpdateInstallation") - - - - - - - - @@ -163,7 +164,7 @@ - if (Util.hasFullAdminRights()) { + if (Util.hasFullAdminRights() || Util.isAdminGroup()) { context.setInstallationDirectory(context.getInstallationDirectory()); } else { if (Util.isAtLeastWindowsVista()) { @@ -369,7 +370,7 @@ return true; context.getBooleanVariable("addToDockAction") - + @@ -398,7 +399,7 @@ return true; - Util.hasFullAdminRights() + Util.hasFullAdminRights() || Util.isAdminGroup() @@ -422,7 +423,7 @@ return true; - !Util.hasFullAdminRights() + !(Util.hasFullAdminRights() || Util.isAdminGroup()) @@ -612,6 +613,57 @@ return true; + + + + + + + + + + + + + SOFTWARE\JabRef + + + false + + + + com.install4j.api.windows.RegistryRoot + HKEY_LOCAL_MACHINE + + + + + + Util.hasFullAdminRights() || Util.isAdminGroup() + + + + + + + SOFTWARE\JabRef + + + false + + + + com.install4j.api.windows.RegistryRoot + HKEY_CURRENT_USER + + + + + + !(Util.hasFullAdminRights() || Util.isAdminGroup()) + + + From 45b3de164a3e27c3ff2b84d3c8bdd1defd07124b Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 13 Jul 2016 16:13:06 +0200 Subject: [PATCH 222/268] Performance improvements for groups (#1552) * Performance improvements for groups by using storing a list of keywords in the entry * Use getFieldOptional * Move getStringAsWords to EntryUtil * Remove unused import --- .../sf/jabref/gui/groups/GroupSelector.java | 3 +- .../sf/jabref/logic/groups/KeywordGroup.java | 39 ++++++++++--- .../jabref/logic/util/strings/StringUtil.java | 2 +- .../net/sf/jabref/model/entry/BibEntry.java | 27 ++++++++- .../net/sf/jabref/model/entry/EntryUtil.java | 13 +++++ .../jabref/logic/groups/KeywordGroupTest.java | 57 +++++++++++++++++++ 6 files changed, 130 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 8780d9aa6434..6a51d3b00af0 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -723,9 +723,8 @@ public void componentClosing() { private void setGroups(GroupTreeNode groupsRoot) { this.groupsRoot = new GroupTreeNodeViewModel(groupsRoot); - // refactor notice: groupsTreeModel::nodeStructureChanged cannot be used, because an NPE will be risen if no groupsTreeModel exists - this.groupsRoot.subscribeToDescendantChanged(source -> groupsTreeModel.nodeStructureChanged(source)); groupsTreeModel = new DefaultTreeModel(this.groupsRoot); + this.groupsRoot.subscribeToDescendantChanged(groupsTreeModel::nodeStructureChanged); groupsTree.setModel(groupsTreeModel); if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_EXPAND_TREE)) { this.groupsRoot.expandSubtree(groupsTree); diff --git a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java index 051c726141f1..b29bd7369d38 100644 --- a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -29,6 +30,7 @@ import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.EntryUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -45,6 +47,7 @@ public class KeywordGroup extends AbstractGroup { private final boolean caseSensitive; private final boolean regExp; private Pattern pattern; + private List searchWords; private static final Log LOGGER = LogFactory.getLog(KeywordGroup.class); @@ -63,6 +66,7 @@ public KeywordGroup(String name, String searchField, if (this.regExp) { compilePattern(); } + this.searchWords = EntryUtil.getStringAsWords(searchExpression); } private void compilePattern() throws ParseException { @@ -197,17 +201,38 @@ public boolean equals(Object o) { @Override public boolean contains(BibEntry entry) { - if (!entry.hasField(searchField)) { - return false; - } - String content = entry.getField(searchField); if (regExp) { - return pattern.matcher(content).find(); + Optional content = entry.getFieldOptional(searchField); + return content.map(value -> pattern.matcher(value).find()).orElse(false); + } + + Set words = entry.getFieldAsWords(searchField); + if (words.isEmpty()) { + return false; } + if (caseSensitive) { - return KeywordGroup.containsWord(searchExpression, content); + return words.containsAll(searchWords); + } + return containsCaseInsensitive(searchWords, words); + } + + private boolean containsCaseInsensitive(List searchText, Set words) { + for (String searchWord : searchText) { + if (!containsCaseInsensitive(searchWord, words)) { + return false; + } + } + return true; + } + + private boolean containsCaseInsensitive(String text, Set words) { + for (String word : words) { + if (word.equalsIgnoreCase(text)) { + return true; + } } - return KeywordGroup.containsWord(searchExpression.toLowerCase(), content.toLowerCase()); + return false; } /** diff --git a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java index 86a6e3bdf6cb..5e08b24b10ac 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java @@ -33,7 +33,7 @@ public class StringUtil { private static final Pattern BRACED_TITLE_CAPITAL_PATTERN = Pattern.compile("\\{[A-Z]+\\}"); - public static final UnicodeToReadableCharMap UNICODE_CHAR_MAP = new UnicodeToReadableCharMap(); + private static final UnicodeToReadableCharMap UNICODE_CHAR_MAP = new UnicodeToReadableCharMap(); /** * Returns the string, after shaving off whitespace at the beginning and end, diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 134102f32bd5..b8bd9b1bb38f 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -22,8 +22,10 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -50,11 +52,15 @@ public class BibEntry implements Cloneable { public static final String KEY_FIELD = "bibtexkey"; protected static final String ID_FIELD = "id"; public static final String KEYWORDS_FIELD = "keywords"; - public static final String DEFAULT_TYPE = "misc"; + private static final String DEFAULT_TYPE = "misc"; private String id; private String type; private Map fields = new HashMap<>(); + /* + * Map to store the words in every field + */ + private Map> fieldsAsWords = new HashMap<>(); // Search and grouping status is stored in boolean fields for quick reference: private boolean searchHit; @@ -362,6 +368,7 @@ public Optional setField(String name, String value) { changed = true; fields.put(fieldName, value); + fieldsAsWords.remove(fieldName); FieldChange change = new FieldChange(this, fieldName, oldValue, value); eventBus.post(new FieldChangedEvent(change)); @@ -389,6 +396,7 @@ public Optional clearField(String name) { changed = true; fields.remove(fieldName); + fieldsAsWords.remove(fieldName); FieldChange change = new FieldChange(this, fieldName, oldValue.get(), null); eventBus.post(new FieldChangedEvent(change)); return Optional.of(change); @@ -620,4 +628,21 @@ public BibEntry withField(String field, String value) { setField(field, value); return this; } + + public Set getFieldAsWords(String field) { + String fieldName = toLowerCase(field); + Set storedList = fieldsAsWords.get(fieldName); + if (storedList != null) { + return storedList; + } else { + String fieldValue = fields.get(fieldName); + if (fieldValue == null) { + return Collections.emptySet(); + } else { + HashSet words = new HashSet<>(EntryUtil.getStringAsWords(fieldValue)); + fieldsAsWords.put(fieldName, words); + return words; + } + } + } } diff --git a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java index 6d6bd11f63fa..cc0d189edf46 100644 --- a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java +++ b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java @@ -1,6 +1,8 @@ package net.sf.jabref.model.entry; +import java.util.Arrays; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import java.util.StringTokenizer; @@ -51,4 +53,15 @@ public static Set getSeparatedKeywords(String keywordString) { public static Set getSeparatedKeywords(BibEntry entry) { return getSeparatedKeywords(entry.getFieldOptional(BibEntry.KEYWORDS_FIELD).orElse(null)); } + + /** + * Returns a list of words contained in the given text. + * Whitespace, comma and semicolon are considered as separator between words. + * + * @param text the input + * @return a list of words + */ + public static List getStringAsWords(String text) { + return Arrays.asList(text.split("[\\s,;]+")); + } } diff --git a/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java index d0816b416b44..38166bfa7c01 100644 --- a/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java @@ -1,10 +1,12 @@ package net.sf.jabref.logic.groups; import net.sf.jabref.importer.fileformat.ParseException; +import net.sf.jabref.model.entry.BibEntry; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class KeywordGroupTest { @@ -22,4 +24,59 @@ public void testToString2() throws ParseException { assertEquals("KeywordGroup:myExplicitGroup;1;author;asdf;0;1;", group.toString()); } + @Test + public void containsSimpleWord() throws Exception { + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + BibEntry entry = new BibEntry().withField("keywords", "test"); + + assertTrue(group.isMatch(entry)); + } + + @Test + public void containsSimpleWordInSentence() throws Exception { + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + BibEntry entry = new BibEntry().withField("keywords", "Some sentence containing test word"); + + assertTrue(group.isMatch(entry)); + } + + @Test + public void containsSimpleWordCommaSeparated() throws Exception { + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + BibEntry entry = new BibEntry().withField("keywords", "Some,list,containing,test,word"); + + assertTrue(group.isMatch(entry)); + } + + @Test + public void containsSimpleWordSemicolonSeparated() throws Exception { + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + BibEntry entry = new BibEntry().withField("keywords", "Some;list;containing;test;word"); + + assertTrue(group.isMatch(entry)); + } + + @Test + public void containsComplexWord() throws Exception { + KeywordGroup group = new KeywordGroup("name", "keywords", "\\H2O", false, false, GroupHierarchyType.INDEPENDENT); + BibEntry entry = new BibEntry().withField("keywords", "\\H2O"); + + assertTrue(group.isMatch(entry)); + } + + @Test + public void containsComplexWordInSentence() throws Exception { + KeywordGroup group = new KeywordGroup("name", "keywords", "\\H2O", false, false, GroupHierarchyType.INDEPENDENT); + BibEntry entry = new BibEntry().withField("keywords", "Some sentence containing \\H2O word"); + + assertTrue(group.isMatch(entry)); + } + + @Test + public void containsWordWithWhitespaceInSentence() throws Exception { + KeywordGroup group = new KeywordGroup("name", "keywords", "test word", false, false, GroupHierarchyType.INDEPENDENT); + BibEntry entry = new BibEntry().withField("keywords", "Some sentence containing test word"); + + assertTrue(group.isMatch(entry)); + } } From fd695d24782266018ee90407cf1210959c238bb2 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 13 Jul 2016 19:37:18 +0200 Subject: [PATCH 223/268] Release v3.5 --- CHANGELOG.md | 47 ++++++++--------------------------------------- README.md | 4 +--- build.gradle | 4 ++-- 3 files changed, 11 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ffe73ed743d..e20708fb2cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,23 +9,21 @@ Here, the categories "Changed" for added and changed functionality, We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#NUM`. -## [Unreleased] +## [3.5] - 2016-07-13 ### Changed - Implemented [#1356](https://github.com/JabRef/jabref/issues/1356): Added a formatter for converting HTML to Unicode - Implemented [#661](https://github.com/JabRef/jabref/issues/661): Introducing a "check for updates" mechnism (manually/automatic at startup) -- [#1485](https://github.com/JabRef/jabref/issues/1485): Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography -- [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view -- Updated German translation +- Implemented [#1338](https://github.com/JabRef/jabref/issues/1338): clicking on a crossref in the main table selects the parent entry and added a button in the entry editor to select the parent entry. +- Implemented [#1485](https://github.com/JabRef/jabref/issues/1485): Biblatex field shorttitle is now exported/imported as standard field ShortTitle to Word bibliography +- Implemented [#1431](https://github.com/JabRef/jabref/issues/1431): Import dialog shows file extensions and filters the view - When resolving duplicate BibTeX-keys there is now an "Ignore" button. "Cancel" and close key now quits the resolving. - The [online forum](http://discourse.jabref.org/) is now directly accessible via the "Help" menu -- Implemented [#1338](https://github.com/JabRef/jabref/issues/1338): clicking on a crossref in the main table selects the parent entry and added a button in the entry editor to select the parent entry. +- Updated German translation ### Fixed - Fixed [#1530](https://github.com/JabRef/jabref/issues/1530): Unescaped hashes in the url field are ignored by the integrity checker -- Springer fetcher now fetches the requested number of entries (not one less as before) - Fixed [#405](https://github.com/JabRef/jabref/issues/405): Added more {} around capital letters in Unicode/HTML to LaTeX conversion to preserve them -- Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file - Fixed [#1476](https://github.com/JabRef/jabref/issues/1476): NPE when importing from SQL DB because of missing DatabaseMode - Fixed [#1481](https://github.com/JabRef/jabref/issues/1481): Mac OS X binary seems broken for JabRef 3.4 release - Fixed [#1430](https://github.com/JabRef/jabref/issues/1430): "review changes" did misinterpret changes @@ -37,37 +35,8 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1534](https://github.com/JabRef/jabref/issues/1534): "Mark entries imported into database" does not work correctly - Fixed [#1500](https://github.com/JabRef/jabref/issues/1500): Renaming of explicit groups now changes entries accordingly - Fixed issue where field changes were not undoable if the time stamp was updated on editing - -### Removed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +- Springer fetcher now fetches the requested number of entries (not one less as before) +- Alleviate multiuser concurrency issue when near simultaneous saves occur to a shared database file ## [3.4] - 2016-06-02 @@ -428,7 +397,7 @@ Since much functionality has changed during development, a release of this versi The changelog of 2.11 and versions before is maintained as [text file](https://github.com/JabRef/jabref/blob/dev_2.11/CHANGELOG) in the [dev_2.11 branch](https://github.com/JabRef/jabref/tree/dev_2.11). -[Unreleased]: https://github.com/JabRef/jabref/compare/v3.4...HEAD +[3.5]: https://github.com/JabRef/jabref/compare/v3.4...v3.5 [3.4]: https://github.com/JabRef/jabref/compare/v3.3...v3.4 [3.3]: https://github.com/JabRef/jabref/compare/v3.2...v3.3 [3.2]: https://github.com/JabRef/jabref/compare/v3.1...v3.2 diff --git a/README.md b/README.md index dedc17e23e0e..cf0f6bb6acd2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# JabRef Development Version +# JabRef Version 3.5 [![Build Status](https://travis-ci.org/JabRef/jabref.svg?branch=master)](https://travis-ci.org/JabRef/jabref) [![Dependency Status](https://www.versioneye.com/user/projects/557f2723386664002000009c/badge.svg?style=flat)](https://www.versioneye.com/user/projects/557f2723386664002000009c) @@ -7,8 +7,6 @@ [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/pr)](http://www.issuestats.com/github/jabref/jabref) [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/issue)](http://www.issuestats.com/github/jabref/jabref) -This version is a development version. Features may not work as expected. - Branches of JabRef development are listed at https://github.com/JabRef/jabref/wiki/Branches. Development builds are available at [builds.jabref.org](http://builds.jabref.org/master/), the [latest release is available via GitHub](https://github.com/JabRef/jabref/releases/latest). diff --git a/build.gradle b/build.gradle index 13bb16f323ac..6830b871d51f 100644 --- a/build.gradle +++ b/build.gradle @@ -33,8 +33,8 @@ apply from: 'eclipse.gradle' apply from: 'localization.gradle' group = "net.sf.jabref" -version = "3.5dev" -project.ext.threeDotVersion = "3.4.0.1" +version = "3.5" +project.ext.threeDotVersion = "3.5.0.0" project.ext.install4jDir = hasProperty("install4jDir") ? getProperty("install4jDir") : (OperatingSystem.current().isWindows() ? 'C:/Program Files/install4j6' : 'install4j6') sourceCompatibility = 1.8 targetCompatibility = 1.8 From a07c2cd2fef0f6aa1e9da9fb6577f9e8b133be9b Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 13 Jul 2016 19:42:55 +0200 Subject: [PATCH 224/268] Show development information --- CHANGELOG.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 +++- build.gradle | 4 ++-- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e20708fb2cc1..102ab8ddf08c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,65 @@ Here, the categories "Changed" for added and changed functionality, "Removed" for removed functionality is used. We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#NUM`. + + +## [Unreleased] + +### Changed + +### Fixed + +### Removed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## [3.5] - 2016-07-13 @@ -397,6 +456,7 @@ Since much functionality has changed during development, a release of this versi The changelog of 2.11 and versions before is maintained as [text file](https://github.com/JabRef/jabref/blob/dev_2.11/CHANGELOG) in the [dev_2.11 branch](https://github.com/JabRef/jabref/tree/dev_2.11). +[Unreleased]: https://github.com/JabRef/jabref/compare/v3.5...HEAD [3.5]: https://github.com/JabRef/jabref/compare/v3.4...v3.5 [3.4]: https://github.com/JabRef/jabref/compare/v3.3...v3.4 [3.3]: https://github.com/JabRef/jabref/compare/v3.2...v3.3 diff --git a/README.md b/README.md index cf0f6bb6acd2..dedc17e23e0e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# JabRef Version 3.5 +# JabRef Development Version [![Build Status](https://travis-ci.org/JabRef/jabref.svg?branch=master)](https://travis-ci.org/JabRef/jabref) [![Dependency Status](https://www.versioneye.com/user/projects/557f2723386664002000009c/badge.svg?style=flat)](https://www.versioneye.com/user/projects/557f2723386664002000009c) @@ -7,6 +7,8 @@ [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/pr)](http://www.issuestats.com/github/jabref/jabref) [![Issue Stats](http://www.issuestats.com/github/jabref/jabref/badge/issue)](http://www.issuestats.com/github/jabref/jabref) +This version is a development version. Features may not work as expected. + Branches of JabRef development are listed at https://github.com/JabRef/jabref/wiki/Branches. Development builds are available at [builds.jabref.org](http://builds.jabref.org/master/), the [latest release is available via GitHub](https://github.com/JabRef/jabref/releases/latest). diff --git a/build.gradle b/build.gradle index 6830b871d51f..51b94d6a9337 100644 --- a/build.gradle +++ b/build.gradle @@ -33,8 +33,8 @@ apply from: 'eclipse.gradle' apply from: 'localization.gradle' group = "net.sf.jabref" -version = "3.5" -project.ext.threeDotVersion = "3.5.0.0" +version = "3.6dev" +project.ext.threeDotVersion = "3.5.0.1" project.ext.install4jDir = hasProperty("install4jDir") ? getProperty("install4jDir") : (OperatingSystem.current().isWindows() ? 'C:/Program Files/install4j6' : 'install4j6') sourceCompatibility = 1.8 targetCompatibility = 1.8 From 7e3bbc1805879a286a8e1bfb9f51f4d3da9c4d24 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 13 Jul 2016 22:04:10 +0200 Subject: [PATCH 225/268] Update log4j dependency from 2.6.1 to 2.6.2 --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 51b94d6a9337..f51f2c41d275 100644 --- a/build.gradle +++ b/build.gradle @@ -109,9 +109,9 @@ dependencies { compile 'com.mashape.unirest:unirest-java:1.4.9' compile 'info.debatty:java-string-similarity:0.13' - compile 'org.apache.logging.log4j:log4j-jcl:2.6.1' - compile 'org.apache.logging.log4j:log4j-api:2.6.1' - compile 'org.apache.logging.log4j:log4j-core:2.6.1' + compile 'org.apache.logging.log4j:log4j-jcl:2.6.2' + compile 'org.apache.logging.log4j:log4j-api:2.6.2' + compile 'org.apache.logging.log4j:log4j-core:2.6.2' testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' From 5697d6e6e8728f218ce8cdde4cfb0f9e974db959 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 13 Jul 2016 23:33:51 +0200 Subject: [PATCH 226/268] Remove install4j watermark at installer divider #1580 --- jabref.install4j | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/jabref.install4j b/jabref.install4j index a6bc97630258..6d9c67c460cf 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -100,7 +100,11 @@ - + + + false + + @@ -543,6 +547,9 @@ return true; true + + false + From bc466590cffa0d6e7b4d8edf925ed058b6b55bce Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 13 Jul 2016 13:25:45 +0200 Subject: [PATCH 227/268] Manually generated the developers list based on the addition to @JabRef/developers Idea based on http://rubyonrails.org/community/ --- DEVELOPERS | 16 +++++++--------- scripts/generate-developers.sh | 34 ---------------------------------- 2 files changed, 7 insertions(+), 43 deletions(-) delete mode 100644 scripts/generate-developers.sh diff --git a/DEVELOPERS b/DEVELOPERS index c8af2a8cffab..5ee93c379682 100644 --- a/DEVELOPERS +++ b/DEVELOPERS @@ -1,9 +1,7 @@ -# This file lists all individuals being part of JabRef's developers team -# For how it is generated, see `scripts/generate-developers.sh`. -Joerg Lenhard -Matthias Geiger -Oliver Kopp -Oscar Gustafsson -Simon Harrer -Stefan Kolb -Tobias Diez +Oliver Kopp (since 2011) +Simon Harrer (since 2014) +Joerg Lenhard (since 2015) +Stefan Kolb (since 2015) +Matthias Geiger (since 2015) +Oscar Gustafsson (since 2015) +Tobias Diez (since 2015) diff --git a/scripts/generate-developers.sh b/scripts/generate-developers.sh deleted file mode 100644 index df5a1db7c41f..000000000000 --- a/scripts/generate-developers.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -set -e - -#Check environment variables -if [ -z $GITHUB_OAUTH_TOKEN ]; then - echo "GITHUB_OAUTH_TOKEN not set"; - exit 1; -fi; - - -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")/.." - -#github requires authorization on JabRef's developers team (id 727640) even if the team is public -#github returns a formatted json. Therefore, we use plain sed to get the field content instead of using jq -userURLs=`curl --silent -H "Authorization: token $GITHUB_OAUTH_TOKEN" https://api.github.com/teams/727640/members | grep \"url\" | sed 's|.*: "\(.*\)".*|\1|'` -#now we have a list of URLs each pointing to a team member - -{ - #generate header - cat <<-'EOF' - # This file lists all individuals being part of JabRef's developers team - # For how it is generated, see `scripts/generate-developers.sh`. - EOF - - #list all developer names alphabetically (sorted by first name) - { - #iterate through all URLss and fetch name info - for userURL in $userURLs; do - name=`curl --silent $userURL | grep "name" | sed 's|.*: "\(.*\)".*|\1|'` - echo $name - done - } | LC_ALL=C.UTF-8 sort - -} > DEVELOPERS \ No newline at end of file From a37501f6ff1a471888710408c0b6e687359349a8 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 13 Jul 2016 20:51:23 +0200 Subject: [PATCH 228/268] Add Christoph Schwentker --- DEVELOPERS | 1 + 1 file changed, 1 insertion(+) diff --git a/DEVELOPERS b/DEVELOPERS index 5ee93c379682..e33a2943f83c 100644 --- a/DEVELOPERS +++ b/DEVELOPERS @@ -5,3 +5,4 @@ Stefan Kolb (since 2015) Matthias Geiger (since 2015) Oscar Gustafsson (since 2015) Tobias Diez (since 2015) +Christoph Schwentker (since 2016) From 4bda9c9c218d84e56d13eab984610ccf70d1fe02 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Thu, 14 Jul 2016 11:43:36 +0200 Subject: [PATCH 229/268] Remove obsolete entry in AUTHORS --- scripts/generate-authors.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/generate-authors.sh b/scripts/generate-authors.sh index 785bd689237b..ee0d51e7d7a3 100755 --- a/scripts/generate-authors.sh +++ b/scripts/generate-authors.sh @@ -41,7 +41,6 @@ cd "$(dirname "$(readlink -f "$BASH_SOURCE")")/.." John Relph Hannes Restel Moritz Ringler - Christoph Schwentker Rudolf Seemann Toralf Senger Manuel Siebeneicher From aa42c16a8b9e7d051ef34ec0b4e8760af56e9a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lenhard?= Date: Thu, 14 Jul 2016 14:14:41 +0200 Subject: [PATCH 230/268] Preserve user comments in bib file (#1471) * Add failing test with preceding comment * Add failing parser test * Improve test naming * Reuse Globals.ENCODING_PREFIX in test * Check explicitly for encoding line and purge it * Add changelog entry * Write out user comments also for modified entries * Add test to check preservation of ENCODING_PREFIX inside an entry * Make BibEntryWriter more robust when dealing with faulty parsed serializations * Add test with user comment in file * Add test that changes and reformats an entry with a user comment * Add test with user comment before String * Preserve newlines also when used with bibtex strings * Add test for serialization of epilog * Fix string detection in test * In case of change, only remove trailing whitespaces between user comments and entry * Remove unused variable * Remove unused import * Reformat changelog entry * Move comment detection logic to BibtexString * Compute user comment in string only once * Move user comment computation to BibEntry * Add test for comment in the same line as BibEntry * Remove unnecessary epilog test * Remove redundant test bib file * Remove redundant asserts * Elevate registry actions * Delete stuff * Revert "Elevate registry actions" This reverts commit b4b288a87f7f2a606b025fd8b3d3b00b150346fb. * Revert "Delete stuff" This reverts commit 67a48859b5b2973f01bb41ffddce802e8825f3ac. * Use optional in assert * Remove duplicate test * Remove unnecessary asserts * Remove unused import of Optional --- CHANGELOG.md | 1 + .../sf/jabref/exporter/BibDatabaseWriter.java | 10 + .../importer/fileformat/BibtexParser.java | 33 ++- .../jabref/logic/bibtex/BibEntryWriter.java | 24 ++- .../net/sf/jabref/model/entry/BibEntry.java | 25 +++ .../sf/jabref/model/entry/BibtexString.java | 24 +++ .../exporter/BibDatabaseWriterTest.java | 61 ++++++ .../importer/fileformat/BibtexParserTest.java | 202 ++++++++++++------ .../logic/bibtex/BibEntryWriterTest.java | 124 ++++++----- .../bibWithUserCommentAndEntryChange.bib | 41 ++++ .../resources/testbib/bibWithUserComments.bib | 43 ++++ src/test/resources/testbib/complex.bib | 2 + 12 files changed, 438 insertions(+), 152 deletions(-) create mode 100644 src/test/resources/testbib/bibWithUserCommentAndEntryChange.bib create mode 100644 src/test/resources/testbib/bibWithUserComments.bib diff --git a/CHANGELOG.md b/CHANGELOG.md index 102ab8ddf08c..3dd3c72536d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed +- [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings ### Fixed diff --git a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java index 244da0b7f7c1..18ddd90a3e38 100644 --- a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java @@ -317,6 +317,8 @@ private void writeString(Writer fw, BibtexString bs, Map r return; } + writeUserCommentsForString(bs, fw); + if(isFirstStringInType) { fw.write(Globals.NEWLINE); } @@ -354,6 +356,14 @@ private void writeString(Writer fw, BibtexString bs, Map r fw.write("}" + Globals.NEWLINE); } + private void writeUserCommentsForString(BibtexString string, Writer out) throws IOException { + String userComments = string.getUserComments(); + + if(!userComments.isEmpty()) { + out.write(userComments + Globals.NEWLINE); + } + } + /** * Write all strings in alphabetical order, modified to produce a safe (for * BibTeX) order of the strings if they reference each other. diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 788abd770693..78da8c784195 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -29,6 +29,7 @@ import java.util.Objects; import java.util.Optional; +import net.sf.jabref.Globals; import net.sf.jabref.MetaData; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.bibtex.FieldContentParser; @@ -323,29 +324,23 @@ private String dumpTextReadSoFarToString() { // if there is no entry found, simply return the content (necessary to parse text remaining after the last entry) if (indexOfAt == -1) { return purgeEOFCharacters(result); - } else { - - //skip all text except newlines and whitespaces before first @. This is necessary to remove the file header - int runningIndex = indexOfAt - 1; - while (runningIndex >= 0) { - if (!Character.isWhitespace(result.charAt(runningIndex))) { + } else if(result.contains(Globals.ENCODING_PREFIX)) { + // purge the encoding line if it exists + int runningIndex = result.indexOf(Globals.ENCODING_PREFIX); + while(runningIndex < indexOfAt) { + if(result.charAt(runningIndex) == '\n') { + break; + } else if(result.charAt(runningIndex) == '\r') { + if(result.charAt(runningIndex + 1) == '\n') { + runningIndex++; + } break; } - runningIndex--; - } - - if(runningIndex > -1) { - // We have to ignore some text at the beginning - // so we view the first line break as the end of the previous text and don't store it - if(result.charAt(runningIndex + 1) == '\r') { - runningIndex++; - } - if(result.charAt(runningIndex + 1) == '\n') { - runningIndex++; - } + runningIndex++; } - return result.substring(runningIndex + 1); + } else { + return result; } } diff --git a/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java index 8cba85933a48..dc3492095369 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java @@ -37,10 +37,10 @@ public void write(BibEntry entry, Writer out, BibDatabaseMode bibDatabaseMode) t /** * Writes the given BibEntry using the given writer * - * @param entry The entry to write - * @param out The writer to use + * @param entry The entry to write + * @param out The writer to use * @param bibDatabaseMode The database mode (bibtex or biblatex) - * @param reformat Should the entry be in any case, even if no change occurred? + * @param reformat Should the entry be in any case, even if no change occurred? */ public void write(BibEntry entry, Writer out, BibDatabaseMode bibDatabaseMode, Boolean reformat) throws IOException { // if the entry has not been modified, write it as it was @@ -48,11 +48,21 @@ public void write(BibEntry entry, Writer out, BibDatabaseMode bibDatabaseMode, B out.write(entry.getParsedSerialization()); return; } + + writeUserComments(entry, out); out.write(Globals.NEWLINE); writeRequiredFieldsFirstRemainingFieldsSecond(entry, out, bibDatabaseMode); out.write(Globals.NEWLINE); } + private void writeUserComments(BibEntry entry, Writer out) throws IOException { + String userComments = entry.getUserComments(); + + if(!userComments.isEmpty()) { + out.write(userComments + Globals.NEWLINE); + } + } + public void writeWithoutPrependedNewlines(BibEntry entry, Writer out, BibDatabaseMode bibDatabaseMode) throws IOException { // if the entry has not been modified, write it as it was if (!entry.hasChanged()) { @@ -71,7 +81,7 @@ public void writeWithoutPrependedNewlines(BibEntry entry, Writer out, BibDatabas * @throws IOException */ private void writeRequiredFieldsFirstRemainingFieldsSecond(BibEntry entry, Writer out, - BibDatabaseMode bibDatabaseMode) throws IOException { + BibDatabaseMode bibDatabaseMode) throws IOException { // Write header with type and bibtex-key. TypedBibEntry typedEntry = new TypedBibEntry(entry, Optional.empty(), bibDatabaseMode); out.write('@' + typedEntry.getTypeForDisplay() + '{'); @@ -127,9 +137,9 @@ private void writeKeyField(BibEntry entry, Writer out) throws IOException { /** * Write a single field, if it has any content. * - * @param entry the entry to write - * @param out the target of the write - * @param name The field name + * @param entry the entry to write + * @param out the target of the write + * @param name The field name * @throws IOException In case of an IO error */ private void writeField(BibEntry entry, Writer out, String name, int indentation) throws IOException { diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index b8bd9b1bb38f..f4c5a86c84ed 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -629,6 +629,31 @@ public BibEntry withField(String field, String value) { return this; } + /* + * Returns user comments (arbitrary text before the entry), if they exist. If not, returns the empty String + */ + public String getUserComments() { + + if (parsedSerialization != null) { + + try { + // get the text before the entry + String prolog = parsedSerialization.substring(0, parsedSerialization.indexOf('@')); + + // delete trailing whitespaces (between entry and text) + prolog = prolog.replaceFirst("\\s+$", ""); + + // if there is any non whitespace text, write it + if (prolog.length() > 0) { + return prolog; + } + } catch (StringIndexOutOfBoundsException ignore) { + // if this occurs a broken parsed serialization has been set, so just do nothing + } + } + return ""; + } + public Set getFieldAsWords(String field) { String fieldName = toLowerCase(field); Set storedList = fieldsAsWords.get(fieldName); diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexString.java b/src/main/java/net/sf/jabref/model/entry/BibtexString.java index 95eb37c3dcdf..125161e2eb4e 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexString.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexString.java @@ -152,4 +152,28 @@ public String getParsedSerialization() { public boolean hasChanged(){ return hasChanged; } + + /* + * Returns user comments (arbitrary text before the string) if there are any. If not returns the empty string + */ + public String getUserComments() { + if(parsedSerialization != null) { + + try { + // get the text before the string + String prolog = parsedSerialization.substring(0, parsedSerialization.indexOf('@')); + + // delete trailing whitespaces (between string and text) + prolog = prolog.replaceFirst("\\s+$", ""); + // if there is any non whitespace text, write it with proper line separation + if (prolog.length() > 0) { + return prolog; + } + } catch(StringIndexOutOfBoundsException ignore) { + // if this occurs a broken parsed serialization has been set, so just do nothing + } + } + + return ""; + } } diff --git a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java index a737d33db304..57fef45bc270 100644 --- a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java @@ -291,6 +291,66 @@ public void roundtrip() throws IOException { } } + @Test + public void roundtripWithUserComment() throws IOException { + Path testBibtexFile = Paths.get("src/test/resources/testbib/bibWithUserComments.bib"); + Charset encoding = StandardCharsets.UTF_8; + ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); + + SavePreferences preferences = new SavePreferences().withEncoding(encoding).withSaveInOriginalOrder(true); + BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), + new Defaults(BibDatabaseMode.BIBTEX)); + + databaseWriter.writePartOfDatabase(stringWriter, context, result.getDatabase().getEntries(), preferences); + try (Scanner scanner = new Scanner(testBibtexFile,encoding.name())) { + assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + } + } + + @Test + public void roundtripWithUserCommentAndEntryChange() throws IOException { + Path testBibtexFile = Paths.get("src/test/resources/testbib/bibWithUserComments.bib"); + Charset encoding = StandardCharsets.UTF_8; + ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); + + BibEntry entry = result.getDatabase().getEntryByKey("1137631").get(); + entry.setField("author", "Mr. Author"); + + SavePreferences preferences = new SavePreferences().withEncoding(encoding).withSaveInOriginalOrder(true); + BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), + new Defaults(BibDatabaseMode.BIBTEX)); + + databaseWriter.writePartOfDatabase(stringWriter, context, result.getDatabase().getEntries(), preferences); + + try (Scanner scanner = new Scanner(Paths.get("src/test/resources/testbib/bibWithUserCommentAndEntryChange.bib"),encoding.name())) { + assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + } + } + + @Test + public void roundtripWithUserCommentBeforeStringAndChange() throws IOException { + Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); + Charset encoding = StandardCharsets.UTF_8; + ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); + + BibtexString string = result.getDatabase().getStringValues().iterator().next(); + if(string.getContent().isEmpty()) { + // do nothing + } else { + string.setContent("my first string"); + } + + SavePreferences preferences = new SavePreferences().withEncoding(encoding).withSaveInOriginalOrder(true); + BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), + new Defaults(BibDatabaseMode.BIBTEX)); + + databaseWriter.writePartOfDatabase(stringWriter, context, result.getDatabase().getEntries(), preferences); + + try (Scanner scanner = new Scanner(testBibtexFile,encoding.name())) { + assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + } + } + @Test public void writeSavedSerializationOfEntryIfUnchanged() throws IOException { BibEntry entry = new BibEntry(); @@ -543,4 +603,5 @@ public void writeEntriesInOriginalOrderWhenNoSaveOrderConfigIsSetInMetadata() th + Globals.NEWLINE , stringWriter.toString()); } + } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java index fc2e8a76fed7..adc87ca23425 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; @@ -312,10 +313,10 @@ public void parseRecognizesMultipleEntries() throws IOException { ParserResult result = BibtexParser .parse(new StringReader( "@article{canh05," - + " author = {Crowston, K. and Annabi, H.},\n" - + " title = {Title A}}\n" - + "@inProceedings{foo," - + " author={Norton Bar}}")); + + " author = {Crowston, K. and Annabi, H.},\n" + + " title = {Title A}}\n" + + "@inProceedings{foo," + + " author={Norton Bar}}")); List parsed = result.getDatabase().getEntries(); List expected = new ArrayList<>(); @@ -430,28 +431,28 @@ public void parseCombinesMultipleKeywordsFields() throws IOException { public void parseRecognizesHeaderButIgnoresEncoding() throws IOException { ParserResult result = BibtexParser.parse(new StringReader( "This file was created with JabRef 2.1 beta 2." - + "\n" - + "Encoding: Cp1252" - + "\n" - + "" - + "\n" - + "@INPROCEEDINGS{CroAnnHow05," - + "\n" - + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.}," - + "\n" - + " title = {Effective work practices for floss development: A model and propositions}," - + "\n" - + " booktitle = {Hawaii International Conference On System Sciences (HICSS)}," - + "\n" - + " year = {2005}," - + "\n" - + " owner = {oezbek}," - + "\n" - + " timestamp = {2006.05.29}," - + "\n" - + " url = {http://james.howison.name/publications.html}" - + "\n" - + "}))")); + + "\n" + + "Encoding: Cp1252" + + "\n" + + "" + + "\n" + + "@INPROCEEDINGS{CroAnnHow05," + + "\n" + + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.}," + + "\n" + + " title = {Effective work practices for floss development: A model and propositions}," + + "\n" + + " booktitle = {Hawaii International Conference On System Sciences (HICSS)}," + + "\n" + + " year = {2005}," + + "\n" + + " owner = {oezbek}," + + "\n" + + " timestamp = {2006.05.29}," + + "\n" + + " url = {http://james.howison.name/publications.html}" + + "\n" + + "}))")); assertEquals(Globals.prefs.getDefaultEncoding(), result.getMetaData().getEncoding()); Collection c = result.getDatabase().getEntries(); @@ -593,20 +594,20 @@ public void parseReturnsEmptyListIfNoEntryRecognized() throws IOException { ParserResult result = BibtexParser .parse(new StringReader( " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.}," - + "\n" - + " title = {Effective work practices for floss development: A model and propositions}," - + "\n" - + " booktitle = {Hawaii International Conference On System Sciences (HICSS)}," - + "\n" - + " year = {2005}," - + "\n" - + " owner = {oezbek}," - + "\n" - + " timestamp = {2006.05.29}," - + "\n" - + " url = {http://james.howison.name/publications.html}" - + "\n" - + "}))")); + + "\n" + + " title = {Effective work practices for floss development: A model and propositions}," + + "\n" + + " booktitle = {Hawaii International Conference On System Sciences (HICSS)}," + + "\n" + + " year = {2005}," + + "\n" + + " owner = {oezbek}," + + "\n" + + " timestamp = {2006.05.29}," + + "\n" + + " url = {http://james.howison.name/publications.html}" + + "\n" + + "}))")); Collection c = result.getDatabase().getEntries(); assertEquals(0, c.size()); } @@ -952,16 +953,16 @@ public void parseRecognizesMultipleStrings() throws IOException { public void parseRecognizesStringAndEntry() throws IOException { ParserResult result = BibtexParser.parse(new StringReader( - "" - + "@string{bourdieu = {Bourdieu, Pierre}}" - + "@book{bourdieu-2002-questions-sociologie, " - + " Address = {Paris}," - + " Author = bourdieu," - + " Isbn = 2707318256," - + " Publisher = {Minuit}," - + " Title = {Questions de sociologie}," - + " Year = 2002" - + "}")); + "" + + "@string{bourdieu = {Bourdieu, Pierre}}" + + "@book{bourdieu-2002-questions-sociologie, " + + " Address = {Paris}," + + " Author = bourdieu," + + " Isbn = 2707318256," + + " Publisher = {Minuit}," + + " Title = {Questions de sociologie}," + + " Year = 2002" + + "}")); assertEquals(1, result.getDatabase().getStringCount()); BibtexString s = result.getDatabase().getStringValues().iterator().next(); @@ -1253,10 +1254,10 @@ public void parseSavesNewlinesBeforeEntryInParsedSerialization() throws IOExcept } @Test - public void parseSavesOnlyRealNewlinesBeforeEntryInParsedSerialization() throws IOException { + public void parseRemovesEncodingLineInParsedSerialization() throws IOException { String testEntry = "@article{test,author={Ed von Test}}"; ParserResult result = BibtexParser.parse( - new StringReader("%Encoding: no" + Globals.NEWLINE + Globals.NEWLINE + Globals.NEWLINE + testEntry)); + new StringReader(Globals.ENCODING_PREFIX + Globals.NEWLINE + Globals.NEWLINE + Globals.NEWLINE + testEntry)); Collection c = result.getDatabase().getEntries(); assertEquals(1, c.size()); @@ -1378,7 +1379,7 @@ public void integrationTestSaveOrderConfig() throws IOException { Optional saveOrderConfig = result.getMetaData().getSaveOrderConfig(); assertEquals(new SaveOrderConfig(false, new SaveOrderConfig.SortCriterion("author", false), - new SaveOrderConfig.SortCriterion("year", true), new SaveOrderConfig.SortCriterion("abstract", false)), + new SaveOrderConfig.SortCriterion("year", true), new SaveOrderConfig.SortCriterion("abstract", false)), saveOrderConfig.get()); } @@ -1387,8 +1388,8 @@ public void integrationTestCustomKeyPattern() throws IOException { ParserResult result = BibtexParser .parse(new StringReader( "@comment{jabref-meta: keypattern_article:articleTest;}" - + Globals.NEWLINE - + "@comment{jabref-meta: keypatterndefault:test;}")); + + Globals.NEWLINE + + "@comment{jabref-meta: keypatterndefault:test;}")); AbstractLabelPattern labelPattern = result.getMetaData().getLabelPattern(); @@ -1412,17 +1413,17 @@ public void integrationTestBiblatexMode() throws IOException { public void integrationTestGroupTree() throws IOException, ParseException { ParserResult result = BibtexParser.parse(new StringReader( "@comment{jabref-meta: groupsversion:3;}" - + Globals.NEWLINE + - "@comment{jabref-meta: groupstree:" - + Globals.NEWLINE - + "0 AllEntriesGroup:;" - + Globals.NEWLINE - + "1 KeywordGroup:Fréchet\\;0\\;keywords\\;FrechetSpace\\;0\\;1\\;;" - + Globals.NEWLINE - + "1 KeywordGroup:Invariant theory\\;0\\;keywords\\;GIT\\;0\\;0\\;;" - + Globals.NEWLINE - + "1 ExplicitGroup:TestGroup\\;0\\;Key1\\;Key2\\;;" - + "}")); + + Globals.NEWLINE + + "@comment{jabref-meta: groupstree:" + + Globals.NEWLINE + + "0 AllEntriesGroup:;" + + Globals.NEWLINE + + "1 KeywordGroup:Fréchet\\;0\\;keywords\\;FrechetSpace\\;0\\;1\\;;" + + Globals.NEWLINE + + "1 KeywordGroup:Invariant theory\\;0\\;keywords\\;GIT\\;0\\;0\\;;" + + Globals.NEWLINE + + "1 ExplicitGroup:TestGroup\\;0\\;Key1\\;Key2\\;;" + + "}")); GroupTreeNode root = result.getMetaData().getGroups(); @@ -1434,7 +1435,7 @@ public void integrationTestGroupTree() throws IOException, ParseException { assertEquals( new KeywordGroup("Invariant theory", "keywords", "GIT", false, false, GroupHierarchyType.INDEPENDENT), root.getChildren().get(1).getGroup()); - assertEquals(Arrays.asList("Key1", "Key2"), ((ExplicitGroup)root.getChildren().get(2).getGroup()).getLegacyEntryKeys()); + assertEquals(Arrays.asList("Key1", "Key2"), ((ExplicitGroup) root.getChildren().get(2).getGroup()).getLegacyEntryKeys()); } @Test @@ -1457,7 +1458,7 @@ public void integrationTestFileDirectories() throws IOException { ParserResult result = BibtexParser .parse(new StringReader( "@comment{jabref-meta: fileDirectory:\\\\Literature\\\\;}" - + "@comment{jabref-meta: fileDirectory-defaultOwner-user:D:\\\\Documents;}")); + + "@comment{jabref-meta: fileDirectory-defaultOwner-user:D:\\\\Documents;}")); assertEquals("\\Literature\\", result.getMetaData().getDefaultFileDirectory().get()); assertEquals("D:\\Documents", result.getMetaData().getUserFileDirectory("defaultOwner-user").get()); @@ -1486,4 +1487,69 @@ public void parseReturnsEntriesInSameOrder() throws IOException { assertEquals(expected, result.getDatabase().getEntries()); } + + @Test + public void parsePrecedingComment() throws IOException { + // @formatter:off + String bibtexEntry = "% Some random comment that should stay here" + Globals.NEWLINE + + "@Article{test," + Globals.NEWLINE + + " Author = {Foo Bar}," + Globals.NEWLINE + + " Journal = {International Journal of Something}," + Globals.NEWLINE + + " Note = {some note}," + Globals.NEWLINE + + " Number = {1}" + Globals.NEWLINE + + "}"; + // @formatter:on + + // read in bibtex string + ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); + + Collection entries = result.getDatabase().getEntries(); + assertEquals(1, entries.size()); + + BibEntry entry = entries.iterator().next(); + assertEquals("test", entry.getCiteKey()); + assertEquals(5, entry.getFieldNames().size()); + Set fields = entry.getFieldNames(); + assertTrue(fields.contains("author")); + assertEquals("Foo Bar", entry.getField("author")); + assertEquals(bibtexEntry, entry.getParsedSerialization()); + } + + @Test + public void parseCommentAndEntryInOneLine() throws IOException { + // @formatter:off + String bibtexEntry = "Some random comment that should stay here @Article{test," + Globals.NEWLINE + + " Author = {Foo Bar}," + Globals.NEWLINE + + " Journal = {International Journal of Something}," + Globals.NEWLINE + + " Note = {some note}," + Globals.NEWLINE + + " Number = {1}" + Globals.NEWLINE + + "}"; + // @formatter:on + + // read in bibtex string + ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); + + Collection entries = result.getDatabase().getEntries(); + assertEquals(1, entries.size()); + + BibEntry entry = entries.iterator().next(); + assertEquals("test", entry.getCiteKey()); + assertEquals(5, entry.getFieldNames().size()); + Set fields = entry.getFieldNames(); + assertTrue(fields.contains("author")); + assertEquals("Foo Bar", entry.getField("author")); + assertEquals(bibtexEntry, entry.getParsedSerialization()); + } + + @Test + public void preserveEncodingPrefixInsideEntry() { + List parsed = BibtexParser.fromString("@article{test,author={" + Globals.ENCODING_PREFIX + "}}"); + + BibEntry expected = new BibEntry(); + expected.setType("article"); + expected.setCiteKey("test"); + expected.setField("author", Globals.ENCODING_PREFIX); + assertEquals(Collections.singletonList(expected), parsed); + } + } diff --git a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java index 3721ae7650ea..be74d915a9f8 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java @@ -83,16 +83,8 @@ public void roundTripTest() throws IOException { // read in bibtex string ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); - Collection entries = result.getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.iterator().next(); - assertEquals("test", entry.getCiteKey()); - assertEquals(5, entry.getFieldNames().size()); - Set fields = entry.getFieldNames(); - assertTrue(fields.contains("author")); - assertEquals("Foo Bar", entry.getField("author")); //write out bibtex string StringWriter stringWriter = new StringWriter(); @@ -115,16 +107,8 @@ public void roundTripWithPrependingNewlines() throws IOException { // read in bibtex string ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); - Collection entries = result.getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.iterator().next(); - assertEquals("test", entry.getCiteKey()); - assertEquals(5, entry.getFieldNames().size()); - Set fields = entry.getFieldNames(); - assertTrue(fields.contains("author")); - assertEquals("Foo Bar", entry.getField("author")); //write out bibtex string StringWriter stringWriter = new StringWriter(); @@ -147,21 +131,12 @@ public void roundTripWithModification() throws IOException { // read in bibtex string ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); - Collection entries = result.getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.iterator().next(); - assertEquals("test", entry.getCiteKey()); - assertEquals(5, entry.getFieldNames().size()); // Modify entry entry.setField("author", "BlaBla"); - Set fields = entry.getFieldNames(); - assertTrue(fields.contains("author")); - assertEquals("BlaBla", entry.getField("author")); - // write out bibtex string StringWriter stringWriter = new StringWriter(); writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); @@ -192,24 +167,14 @@ public void roundTripWithCamelCasingInTheOriginalEntryAndResultInLowerCase() thr // read in bibtex string ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); - Collection entries = result.getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.iterator().next(); - assertEquals("test", entry.getCiteKey()); - assertEquals(6, entry.getFieldNames().size()); // modify entry entry.setField("author", "BlaBla"); - Set fields = entry.getFieldNames(); - assertTrue(fields.contains("author")); - assertEquals("BlaBla", entry.getField("author")); - //write out bibtex string StringWriter stringWriter = new StringWriter(); - writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); String actual = stringWriter.toString(); @@ -238,16 +203,8 @@ public void roundTripWithAppendedNewlines() throws IOException { // read in bibtex string ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); - Collection entries = result.getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.iterator().next(); - assertEquals("test", entry.getCiteKey()); - assertEquals(5, entry.getFieldNames().size()); - Set fields = entry.getFieldNames(); - assertTrue(fields.contains("author")); - assertEquals("Foo Bar", entry.getField("author")); //write out bibtex string StringWriter stringWriter = new StringWriter(); @@ -279,16 +236,8 @@ public void multipleWritesWithoutModification() throws IOException { private String testSingleWrite(String bibtexEntry) throws IOException { // read in bibtex string ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); - Collection entries = result.getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.iterator().next(); - assertEquals("test", entry.getCiteKey()); - assertEquals(5, entry.getFieldNames().size()); - Set fields = entry.getFieldNames(); - assertTrue(fields.contains("author")); - assertEquals("Foo Bar", entry.getField("author")); //write out bibtex string StringWriter stringWriter = new StringWriter(); @@ -311,16 +260,13 @@ public void monthFieldSpecialSyntax() throws IOException { // read in bibtex string ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); - Collection entries = result.getDatabase().getEntries(); - assertEquals(1, entries.size()); - BibEntry entry = entries.iterator().next(); - assertEquals("test", entry.getCiteKey()); - assertEquals(4, entry.getFieldNames().size()); + + // modify month field Set fields = entry.getFieldNames(); assertTrue(fields.contains("month")); - assertEquals("#mar#", entry.getField("month")); + assertEquals("#mar#", entry.getFieldOptional("month").get()); //write out bibtex string StringWriter stringWriter = new StringWriter(); @@ -351,7 +297,6 @@ public void addFieldWithLongerLength() throws IOException { //write out bibtex string StringWriter stringWriter = new StringWriter(); - writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); String actual = stringWriter.toString(); @@ -403,4 +348,67 @@ public void trimFieldContents() throws IOException { assertEquals(expected, actual); } + + @Test + public void roundTripWithPrecedingCommentTest() throws IOException { + // @formatter:off + String bibtexEntry = "% Some random comment that should stay here" + Globals.NEWLINE + + "@Article{test," + Globals.NEWLINE + + " Author = {Foo Bar}," + Globals.NEWLINE + + " Journal = {International Journal of Something}," + Globals.NEWLINE + + " Note = {some note}," + Globals.NEWLINE + + " Number = {1}" + Globals.NEWLINE + + "}"; + // @formatter:on + + // read in bibtex string + ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); + Collection entries = result.getDatabase().getEntries(); + BibEntry entry = entries.iterator().next(); + + //write out bibtex string + StringWriter stringWriter = new StringWriter(); + writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); + String actual = stringWriter.toString(); + + assertEquals(bibtexEntry, actual); + } + + @Test + public void roundTripWithPrecedingCommentAndModificationTest() throws IOException { + // @formatter:off + String bibtexEntry = "% Some random comment that should stay here" + Globals.NEWLINE + + "@Article{test," + Globals.NEWLINE + + " Author = {Foo Bar}," + Globals.NEWLINE + + " Journal = {International Journal of Something}," + Globals.NEWLINE + + " Note = {some note}," + Globals.NEWLINE + + " Number = {1}" + Globals.NEWLINE + + "}"; + // @formatter:on + + // read in bibtex string + ParserResult result = BibtexParser.parse(new StringReader(bibtexEntry)); + Collection entries = result.getDatabase().getEntries(); + BibEntry entry = entries.iterator().next(); + + // change the entry + entry.setField("author", "John Doe"); + + //write out bibtex string + StringWriter stringWriter = new StringWriter(); + writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); + String actual = stringWriter.toString(); + // @formatter:off + String expected = "% Some random comment that should stay here" + Globals.NEWLINE + Globals.NEWLINE + + "@Article{test," + Globals.NEWLINE + + " author = {John Doe}," + Globals.NEWLINE + + " journal = {International Journal of Something}," + Globals.NEWLINE + + " number = {1}," + Globals.NEWLINE + + " note = {some note}," + Globals.NEWLINE + + "}" + Globals.NEWLINE; + // @formatter:on + + assertEquals(expected, actual); + } + } diff --git a/src/test/resources/testbib/bibWithUserCommentAndEntryChange.bib b/src/test/resources/testbib/bibWithUserCommentAndEntryChange.bib new file mode 100644 index 000000000000..ea17f6aaae5a --- /dev/null +++ b/src/test/resources/testbib/bibWithUserCommentAndEntryChange.bib @@ -0,0 +1,41 @@ +% Encoding: UTF-8 + +@Preamble{preamble} + +@String{firstString = {my first string}} +@String{secondString = {}} + +@ARTICLE{1102917, + author = {E. Bardram}, + title = {The trouble with login: on usability and computer security in ubiquitous + computing}, + journal = {Personal Ubiquitous Comput.}, + year = {2005}, + volume = {9}, + pages = {357--367}, + number = {6}, + address = {London, UK}, + bdsk-url-1 = {http://dx.doi.org/10.1007/s00779-005-0347-6}, + doi = {http://dx.doi.org/10.1007/s00779-005-0347-6}, + issn = {1617-4909}, + publisher = {Springer-Verlag} +} + +This is some arbitrary user comment that should be preserved + +@InProceedings{1137631, + author = {Mr. Author}, + title = {Extending XP practices to support security requirements engineering}, + booktitle = {SESS '06: Proceedings of the 2006 international workshop on Software engineering for secure systems}, + year = {2006}, + pages = {11--18}, + address = {New York, NY, USA}, + publisher = {ACM}, + bdsk-url-1 = {http://doi.acm.org/10.1145/1137627.1137631}, + doi = {http://doi.acm.org/10.1145/1137627.1137631}, + file = {:/Volumes/iDisk/Freie Universität Berlin/Semester 9/Softwareprozesse/p11-bostrom.pdf:PDF}, + isbn = {1-59593-411-1}, + location = {Shanghai, China}, +} + +@Comment{jabref-meta: databaseType:bibtex;} diff --git a/src/test/resources/testbib/bibWithUserComments.bib b/src/test/resources/testbib/bibWithUserComments.bib new file mode 100644 index 000000000000..8148c3b6d636 --- /dev/null +++ b/src/test/resources/testbib/bibWithUserComments.bib @@ -0,0 +1,43 @@ +% Encoding: UTF-8 + +@Preamble{preamble} + +@String{firstString = {my first string}} +@String{secondString = {}} + +@ARTICLE{1102917, + author = {E. Bardram}, + title = {The trouble with login: on usability and computer security in ubiquitous + computing}, + journal = {Personal Ubiquitous Comput.}, + year = {2005}, + volume = {9}, + pages = {357--367}, + number = {6}, + address = {London, UK}, + bdsk-url-1 = {http://dx.doi.org/10.1007/s00779-005-0347-6}, + doi = {http://dx.doi.org/10.1007/s00779-005-0347-6}, + issn = {1617-4909}, + publisher = {Springer-Verlag} +} + +This is some arbitrary user comment that should be preserved + +@INPROCEEDINGS{1137631, + author = {Gustav Bostr\"{o}m and Jaana W\"{a}yrynen and Marine Bod\'{e}n and + Konstantin Beznosov and Philippe Kruchten}, + title = {Extending XP practices to support security requirements engineering}, + booktitle = {SESS '06: Proceedings of the 2006 international workshop on Software + engineering for secure systems}, + year = {2006}, + pages = {11--18}, + address = {New York, NY, USA}, + publisher = {ACM}, + bdsk-url-1 = {http://doi.acm.org/10.1145/1137627.1137631}, + doi = {http://doi.acm.org/10.1145/1137627.1137631}, + file = {:/Volumes/iDisk/Freie Universität Berlin/Semester 9/Softwareprozesse/p11-bostrom.pdf:PDF}, + isbn = {1-59593-411-1}, + location = {Shanghai, China} +} + +@Comment{jabref-meta: databaseType:bibtex;} diff --git a/src/test/resources/testbib/complex.bib b/src/test/resources/testbib/complex.bib index 09ecb967c410..ee64be35dc52 100644 --- a/src/test/resources/testbib/complex.bib +++ b/src/test/resources/testbib/complex.bib @@ -2,6 +2,8 @@ @Preamble{preamble} +This is some arbitrary user comment that should be preserved + @String{firstString = {my first string}} @String{secondString = {}} From bc56ab65256ca089ec4160405406bd7f65206c49 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 15 Jul 2016 09:01:14 +0200 Subject: [PATCH 231/268] Fixed #1264 (#1581) * Fixed #1264 * Code improvement * Added tests * Fixed comments and a removed a code label --- CHANGELOG.md | 2 + src/main/java/net/sf/jabref/Globals.java | 4 +- .../bibtexfields/UnicodeToLatexFormatter.java | 9 ++-- .../format/LatexToUnicodeFormatter.java | 45 ++++++++++++++----- .../strings/HTMLUnicodeConversionMaps.java | 23 +++++++--- .../format/LatexToUnicodeFormatterTest.java | 38 +++++++++++++++- 6 files changed, 95 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dd3c72536d3..7f00571c81fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings ### Fixed +- Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly +- LaTeX to Unicode converter now handles combining accents ### Removed diff --git a/src/main/java/net/sf/jabref/Globals.java b/src/main/java/net/sf/jabref/Globals.java index 6e8577b5ed1d..7fb2cf06a5b9 100644 --- a/src/main/java/net/sf/jabref/Globals.java +++ b/src/main/java/net/sf/jabref/Globals.java @@ -53,8 +53,8 @@ public class Globals { public static final ImportFormatReader IMPORT_FORMAT_READER = new ImportFormatReader(); - - public static final String SPECIAL_COMMAND_CHARS = "\"`^~'c="; + // Non-letters which are used to denote accents in LaTeX-commands, e.g., in {\"{a}} + public static final String SPECIAL_COMMAND_CHARS = "\"`^~'=.|"; // In the main program, this field is initialized in JabRef.java // Each test case initializes this field if required diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java index 7c366134364d..793fc1deecf8 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java @@ -15,8 +15,8 @@ */ package net.sf.jabref.logic.formatter.bibtexfields; +import java.util.Map; import java.util.Objects; -import java.util.Set; import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.l10n.Localization; @@ -39,10 +39,9 @@ public String format(String text) { } // Standard symbols - Set chars = HTMLUnicodeConversionMaps.UNICODE_LATEX_CONVERSION_MAP.keySet(); - for (Character character : chars) { - result = result.replace(character.toString(), - HTMLUnicodeConversionMaps.UNICODE_LATEX_CONVERSION_MAP.get(character)); + for (Map.Entry unicodeLatexPair : HTMLUnicodeConversionMaps.UNICODE_LATEX_CONVERSION_MAP + .entrySet()) { + result = result.replace(unicodeLatexPair.getKey(), unicodeLatexPair.getValue()); } // Combining accents diff --git a/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java b/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java index abe2818fc414..821c70b882cc 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatter.java @@ -31,6 +31,7 @@ public class LatexToUnicodeFormatter implements LayoutFormatter, Formatter { private static final Map CHARS = HTMLUnicodeConversionMaps.LATEX_UNICODE_CONVERSION_MAP; + private static final Map ACCENTS = HTMLUnicodeConversionMaps.UNICODE_ESCAPED_ACCENTS; @Override public String getName() { @@ -74,6 +75,7 @@ public String format(String inField) { } else { sb.append((String) result); } + } escaped = true; incommand = true; @@ -88,28 +90,34 @@ public String format(String inField) { sb.append(c); } else { currentCommand.append(c); - testCharCom: if ((currentCommand.length() == 1) - && Globals.SPECIAL_COMMAND_CHARS.contains(currentCommand.toString())) { + if ((currentCommand.length() == 1) + && Globals.SPECIAL_COMMAND_CHARS.contains(currentCommand.toString()) + && !(i >= (field.length() - 1))) { // This indicates that we are in a command of the type // \^o or \~{n} - if (i >= (field.length() - 1)) { - break testCharCom; - } String command = currentCommand.toString(); i++; c = field.charAt(i); - String combody; + String commandBody; if (c == '{') { String part = StringUtil.getPart(field, i, false); i += part.length(); - combody = part; + commandBody = part; } else { - combody = field.substring(i, i + 1); + commandBody = field.substring(i, i + 1); } - Object result = LatexToUnicodeFormatter.CHARS.get(command + combody); + Object result = LatexToUnicodeFormatter.CHARS.get(command + commandBody); - if (result != null) { + if (result == null) { + // Use combining accents if argument is single character or empty + if (commandBody.length() <= 1) { + String accent = LatexToUnicodeFormatter.ACCENTS.get(command); + if (accent != null) { + sb.append(commandBody).append(accent); + } + } + } else { sb.append((String) result); } @@ -152,28 +160,43 @@ public String format(String inField) { if (argument != null) { // handle common case of general latex command Object result = LatexToUnicodeFormatter.CHARS.get(command + argument); + // If found, then use translated version. If not, then keep // the // text of the parameter intact. if (result == null) { - sb.append(argument); + // Use combining accents if argument is single character or empty + if (argument.length() <= 1) { + String accent = LatexToUnicodeFormatter.ACCENTS.get(command); + if (accent != null) { + sb.append(argument).append(accent); + } else { + sb.append(argument); + } + } else { + sb.append(argument); + } } else { sb.append((String) result); } + } } else if (c == '}') { // This end brace terminates a command. This can be the case in // constructs like {\aa}. The correct behaviour should be to // substitute the evaluated command and swallow the brace: Object result = LatexToUnicodeFormatter.CHARS.get(command); + if (result == null) { // If the command is unknown, just print it: sb.append(command); } else { sb.append((String) result); } + } else { Object result = LatexToUnicodeFormatter.CHARS.get(command); + if (result == null) { sb.append(command); } else { diff --git a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java index 93695cfa27ea..c74213c79001 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java @@ -509,14 +509,14 @@ public class HTMLUnicodeConversionMaps { {"", "VerticalLine", "|"}, // Vertical bar {"125", "rbrace", "\\}"}, // Right curly bracket {"", "rcub", "\\}"}, // Right curly bracket - {"138", "", "{{\\v{S}}}"}, // Line tabulation set + // {"138", "", "{{\\v{S}}}"}, // Line tabulation set // {"141", "", ""}, // Reverse line feed {"145", "", "`"}, // Apostrophe {"146", "", "'"}, // Apostrophe {"147", "", "``"}, // Quotation mark {"148", "", "''"}, // Quotation mark {"150", "", "--"}, // En dash - {"154", "", "{\\v{s}}"}, // Single character introducer + // {"154", "", "{\\v{s}}"}, // Single character introducer {"260", "Aogon", "{{\\k{A}}}"}, // capital A with ogonek {"261", "aogon", "{\\k{a}}"}, // small a with ogonek {"262", "Cacute", "{{\\'{C}}}"}, // capital C with acute @@ -574,7 +574,7 @@ public class HTMLUnicodeConversionMaps { {"", "Hacek", "{\\v{}}"}, // Caron {"728", "breve", "{\\u{}}"}, // Breve {"", "Breve", "{\\u{}}"}, // Breve - {"729", "dot", "{\\\\.{}}"}, // Dot above + {"729", "dot", "{\\.{}}"}, // Dot above {"730", "ring", "{\\r{}}"}, // Ring above {"731", "ogon", "{\\k{}}"}, // Ogonek {"733", "dblac", "{{\\H{}}}"}, // Double acute @@ -744,8 +744,9 @@ public class HTMLUnicodeConversionMaps { public static final Map HTML_LATEX_CONVERSION_MAP = new HashMap<>(); public static final Map ESCAPED_ACCENTS = new HashMap<>(); + public static final Map UNICODE_ESCAPED_ACCENTS = new HashMap<>(); public static final Map NUMERICAL_LATEX_CONVERSION_MAP = new HashMap<>(); - public static final Map UNICODE_LATEX_CONVERSION_MAP = new HashMap<>(); + public static final Map UNICODE_LATEX_CONVERSION_MAP = new HashMap<>(); public static final Map LATEX_HTML_CONVERSION_MAP = new HashMap<>(); public static final Map LATEX_UNICODE_CONVERSION_MAP = new HashMap<>(); @@ -765,10 +766,10 @@ public class HTMLUnicodeConversionMaps { if (!(aConversionList[0].isEmpty())) { NUMERICAL_LATEX_CONVERSION_MAP.put(Integer.decode(aConversionList[0]), aConversionList[2]); if (Integer.decode(aConversionList[0]) > 128) { - Character c = (char) Integer.decode(aConversionList[0]).intValue(); - UNICODE_LATEX_CONVERSION_MAP.put(c, aConversionList[2]); + String unicodeSymbol = String.valueOf(Character.toChars(Integer.decode(aConversionList[0]))); + UNICODE_LATEX_CONVERSION_MAP.put(unicodeSymbol, aConversionList[2]); if (!strippedLaTeX.isEmpty()) { - LATEX_UNICODE_CONVERSION_MAP.put(strippedLaTeX, c.toString()); + LATEX_UNICODE_CONVERSION_MAP.put(strippedLaTeX, unicodeSymbol); } } } @@ -776,6 +777,8 @@ public class HTMLUnicodeConversionMaps { } for (String[] anAccentList : ACCENT_LIST) { ESCAPED_ACCENTS.put(Integer.decode(anAccentList[0]), anAccentList[1]); + UNICODE_ESCAPED_ACCENTS.put(anAccentList[1], + String.valueOf(Character.toChars(Integer.decode(anAccentList[0])))); } // Manually added values which are killed by cleanLaTeX LATEX_HTML_CONVERSION_MAP.put("$", "$"); @@ -784,6 +787,12 @@ public class HTMLUnicodeConversionMaps { // Manual corrections LATEX_HTML_CONVERSION_MAP.put("AA", "Å"); // Overwritten by Å which is less supported LATEX_UNICODE_CONVERSION_MAP.put("AA", "Å"); // Overwritten by Ångstrom symbol + + // Manual additions + // Support relax to the extent that it is simply removed + LATEX_HTML_CONVERSION_MAP.put("relax", ""); + LATEX_UNICODE_CONVERSION_MAP.put("relax", ""); + } private static String cleanLaTeX(String escapedString) { diff --git a/src/test/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatterTest.java b/src/test/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatterTest.java index a894506579b4..2c6a98a92c8f 100644 --- a/src/test/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/format/LatexToUnicodeFormatterTest.java @@ -51,9 +51,23 @@ public void testFormatStripLatexCommands() { } @Test - public void testEquations() { + public void testFormatTextit() { + // See #1464 + assertEquals("text", formatter.format("\\textit{text}")); + } + + @Test + public void testEscapedDollarSign() { assertEquals("$", formatter.format("\\$")); + } + + @Test + public void testEquationsSingleSymbol() { assertEquals("σ", formatter.format("$\\sigma$")); + } + + @Test + public void testEquationsMoreComplicatedFormatting() { assertEquals("A 32\u00A0mA ΣΔ-modulator", formatter.format("A 32~{mA} {$\\Sigma\\Delta$}-modulator")); } @@ -61,4 +75,26 @@ public void testEquations() { public void formatExample() { assertEquals("Mönch", formatter.format(formatter.getExampleInput())); } + + @Test + public void testChi() { + // See #1464 + assertEquals("χ", formatter.format("$\\chi$")); + } + + @Test + public void testSWithCaron() { + // Bug #1264 + assertEquals("Š", formatter.format("{\\v{S}}")); + } + + @Test + public void testCombiningAccentsCase1() { + assertEquals("ḩ", formatter.format("{\\c{h}}")); + } + + @Test + public void testCombiningAccentsCase2() { + assertEquals("a͍", formatter.format("\\spreadlips{a}")); + } } From 76cef63d003ba1f87d74ba3f46c1731d12054b1c Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 15 Jul 2016 09:55:59 +0200 Subject: [PATCH 232/268] Fixed #1527 and some refactoring/cleanups (#1583) * Fixed #1527 and some refactoring/cleanups * Added method isInternalField --- CHANGELOG.md | 1 + .../jabref/gui/mergeentries/MergeEntries.java | 108 ++---------------- .../gui/mergeentries/MergeEntryDOIDialog.java | 33 ++++-- .../logic/util/strings/DiffHighlighting.java | 98 ++++++++++++++++ .../sf/jabref/model/database/BibDatabase.java | 3 +- .../model/entry/InternalBibtexFields.java | 4 + src/main/resources/l10n/JabRef_da.properties | 1 - src/main/resources/l10n/JabRef_de.properties | 1 - src/main/resources/l10n/JabRef_en.properties | 1 - src/main/resources/l10n/JabRef_es.properties | 1 - src/main/resources/l10n/JabRef_fa.properties | 1 - src/main/resources/l10n/JabRef_fr.properties | 1 - src/main/resources/l10n/JabRef_in.properties | 1 - src/main/resources/l10n/JabRef_it.properties | 1 - src/main/resources/l10n/JabRef_ja.properties | 1 - src/main/resources/l10n/JabRef_nl.properties | 1 - src/main/resources/l10n/JabRef_no.properties | 1 - .../resources/l10n/JabRef_pt_BR.properties | 1 - src/main/resources/l10n/JabRef_ru.properties | 1 - src/main/resources/l10n/JabRef_sv.properties | 1 - src/main/resources/l10n/JabRef_tr.properties | 1 - src/main/resources/l10n/JabRef_vi.properties | 1 - src/main/resources/l10n/JabRef_zh.properties | 1 - .../util/strings/DiffHighlightingTest.java} | 30 ++--- 24 files changed, 153 insertions(+), 141 deletions(-) create mode 100644 src/main/java/net/sf/jabref/logic/util/strings/DiffHighlighting.java rename src/test/java/net/sf/jabref/{gui/mergeentries/MergeEntriesTest.java => logic/util/strings/DiffHighlightingTest.java} (57%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f00571c81fb..fd5b435c1162 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Fixed - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly - LaTeX to Unicode converter now handles combining accents +- Fixed [#1527](https://github.com/JabRef/jabref/issues/1527): 'Get BibTeX data from DOI' Removes Marking ### Removed diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java index 08a2a5e0f12b..8b58071c2a83 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java @@ -19,14 +19,11 @@ import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -41,6 +38,7 @@ import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.JTextPane; +import javax.swing.SwingUtilities; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; @@ -51,15 +49,15 @@ import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.formatter.casechanger.SentenceCaseFormatter; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.strings.DiffHighlighting; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.ColumnSpec; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.RowSpec; -import difflib.Delta; -import difflib.DiffUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -89,10 +87,6 @@ public class MergeEntries { Localization.lang("Show symmetric diff") + " - " + Localization.lang("word"), Localization.lang("Show symmetric diff") + " - " + Localization.lang("character")}; - private static final String ADDITION_START = ""; - private static final String REMOVAL_START = ""; - private static final String CHANGE_START = ""; - private static final String TAG_END = ""; private static final String HTML_START = ""; private static final String HTML_END = ""; private static final String BODY_STYLE = "body{font:sans-serif}"; @@ -352,10 +346,10 @@ private void setupFields() { allFields.addAll(leftEntry.getFieldNames()); allFields.addAll(rightEntry.getFieldNames()); - // Remove field starting with __ + // Remove internal fields Set toberemoved = new TreeSet<>(); for (String field : allFields) { - if (field.startsWith("__")) { + if (InternalBibtexFields.isInternalField(field)) { toberemoved.add(field); } } @@ -371,19 +365,19 @@ private void updateTextPanes(Collection fields) { case 0: // Plain text break; case 1: // Latexdiff style - word - rightString = generateDiffHighlighting(leftString, rightString, " "); + rightString = DiffHighlighting.generateDiffHighlighting(leftString, rightString, " "); break; case 2: // Latexdiff style - character - rightString = generateDiffHighlighting(leftString, rightString, ""); + rightString = DiffHighlighting.generateDiffHighlighting(leftString, rightString, ""); break; case 3: // Symmetric style - word - String tmpLeftString = generateSymmetricHighlighting(leftString, rightString, " "); - rightString = generateSymmetricHighlighting(rightString, leftString, " "); + String tmpLeftString = DiffHighlighting.generateSymmetricHighlighting(leftString, rightString, " "); + rightString = DiffHighlighting.generateSymmetricHighlighting(rightString, leftString, " "); leftString = tmpLeftString; break; case 4: // Symmetric style - character - tmpLeftString = generateSymmetricHighlighting(leftString, rightString, ""); - rightString = generateSymmetricHighlighting(rightString, leftString, ""); + tmpLeftString = DiffHighlighting.generateSymmetricHighlighting(leftString, rightString, ""); + rightString = DiffHighlighting.generateSymmetricHighlighting(rightString, leftString, ""); leftString = tmpLeftString; break; default: // Shouldn't happen @@ -396,7 +390,7 @@ private void updateTextPanes(Collection fields) { rightTextPanes.get(field).setText(HTML_START + rightString + HTML_END); } } - javax.swing.SwingUtilities.invokeLater(() -> scrollPane.getVerticalScrollBar() + SwingUtilities.invokeLater(() -> scrollPane.getVerticalScrollBar() .setValue(Math.min(scrollPane.getVerticalScrollBar().getMaximum(), oldScrollPaneValue))); } @@ -412,84 +406,6 @@ private JTextPane getStyledTextPane() { return pane; } - public static String generateDiffHighlighting(String baseString, String modifiedString, String separator) { - Objects.requireNonNull(separator); - if ((baseString != null) && (modifiedString != null)) { - List stringList = new ArrayList<>(Arrays.asList(baseString.split(separator))); - List> deltaList = new ArrayList<>( - DiffUtils.diff(stringList, Arrays.asList(modifiedString.split(separator))).getDeltas()); - Collections.reverse(deltaList); - for (Delta delta : deltaList) { - int startPos = delta.getOriginal().getPosition(); - List lines = delta.getOriginal().getLines(); - int offset = 0; - switch (delta.getType()) { - case CHANGE: - for (String line : lines) { - stringList.set(startPos + offset, (offset == 0 ? REMOVAL_START : "") + line); - offset++; - } - stringList.set((startPos + offset) - 1, - stringList.get((startPos + offset) - 1) + TAG_END + separator + ADDITION_START - + String.join(separator, delta.getRevised().getLines()) + TAG_END); - break; - case DELETE: - for (String line : lines) { - stringList.set(startPos + offset, (offset == 0 ? REMOVAL_START : "") + line); - offset++; - } - stringList.set((startPos + offset) - 1, - stringList.get((startPos + offset) - 1) + TAG_END); - break; - case INSERT: - stringList.add(delta.getOriginal().getPosition(), - ADDITION_START + String.join(separator, delta.getRevised().getLines()) + TAG_END); - break; - default: - break; - } - } - return String.join(separator, stringList); - } - return modifiedString; - } - - public static String generateSymmetricHighlighting(String baseString, String modifiedString, String separator) { - if ((baseString != null) && (modifiedString != null)) { - List stringList = new ArrayList<>(Arrays.asList(baseString.split(separator))); - List> deltaList = new ArrayList<>(DiffUtils - .diff(stringList, new ArrayList<>(Arrays.asList(modifiedString.split(separator)))).getDeltas()); - Collections.reverse(deltaList); - for (Delta delta : deltaList) { - int startPos = delta.getOriginal().getPosition(); - List lines = delta.getOriginal().getLines(); - int offset = 0; - switch (delta.getType()) { - case CHANGE: - for (String line : lines) { - stringList.set(startPos + offset, (offset == 0 ? CHANGE_START : "") + line); - offset++; - } - stringList.set((startPos + offset) - 1, stringList.get((startPos + offset) - 1) + TAG_END); - break; - case DELETE: - for (String line : lines) { - stringList.set(startPos + offset, (offset == 0 ? ADDITION_START : "") + line); - offset++; - } - stringList.set((startPos + offset) - 1, stringList.get((startPos + offset) - 1) + TAG_END); - break; - case INSERT: - break; - default: - break; - } - } - return String.join(separator, stringList); - } - return modifiedString; - } - /** * @return Merged BibEntry */ diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java index ca2d0a66efee..88f683f1ff7e 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java @@ -15,6 +15,7 @@ */ package net.sf.jabref.gui.mergeentries; +import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -32,6 +33,7 @@ import net.sf.jabref.importer.fetcher.DOItoBibTeXFetcher; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.layout.CellConstraints; @@ -62,7 +64,8 @@ public MergeEntryDOIDialog(BasePanel panel) { this.panel = panel; if (panel.getSelectedEntries().size() != 1) { - JOptionPane.showMessageDialog(panel.frame(), Localization.lang("Select one entry."), + JOptionPane.showMessageDialog(panel.frame(), + Localization.lang("This operation requires exactly one item to be selected."), Localization.lang("Merge entry with DOI information"), JOptionPane.INFORMATION_MESSAGE); this.dispose(); return; @@ -70,12 +73,17 @@ public MergeEntryDOIDialog(BasePanel panel) { this.originalEntry = panel.getSelectedEntries().get(0); panel.output(Localization.lang("Fetching info based on DOI")); - this.doiEntry = doiFetcher.getEntryFromDOI(this.originalEntry.getField("doi")).orElse(null); + Optional doi = this.originalEntry.getFieldOptional("doi"); + + if (doi.isPresent()) { + this.doiEntry = doiFetcher.getEntryFromDOI(doi.get()).orElse(null); + } if (this.doiEntry == null) { panel.output(""); JOptionPane.showMessageDialog(panel.frame(), - Localization.lang("Cannot get info based on given DOI: %0", this.originalEntry.getField("doi")), + Localization.lang("Cannot get info based on given DOI: %0", + doi.orElse(Localization.lang("No DOI found"))), Localization.lang("Merge entry with DOI information"), JOptionPane.INFORMATION_MESSAGE); this.dispose(); return; @@ -162,21 +170,22 @@ private void buttonPressed(String button) { // fields for (String field : jointFields) { - String originalString = originalEntry.getField(field); - String mergedString = mergedEntry.getField(field); - if ((originalString == null) || !originalString.equals(mergedEntry.getField(field))) { - originalEntry.setField(field, mergedString); - ce.addEdit(new UndoableFieldChange(originalEntry, field, originalString, mergedString)); + Optional originalString = originalEntry.getFieldOptional(field); + Optional mergedString = mergedEntry.getFieldOptional(field); + if (!originalString.isPresent() || !originalString.equals(mergedString)) { + originalEntry.setField(field, mergedString.get()); // mergedString always present + ce.addEdit(new UndoableFieldChange(originalEntry, field, originalString.orElse(null), + mergedString.get())); edited = true; } } - // Remove fields which are not in the merged entry + // Remove fields which are not in the merged entry, unless they are internal fields for (String field : originalFields) { - if (!jointFields.contains(field)) { - String originalString = originalEntry.getField(field); + if (!jointFields.contains(field) && !InternalBibtexFields.isInternalField(field)) { + Optional originalString = originalEntry.getFieldOptional(field); originalEntry.clearField(field); - ce.addEdit(new UndoableFieldChange(originalEntry, field, originalString, null)); + ce.addEdit(new UndoableFieldChange(originalEntry, field, originalString.get(), null)); // originalString always present edited = true; } } diff --git a/src/main/java/net/sf/jabref/logic/util/strings/DiffHighlighting.java b/src/main/java/net/sf/jabref/logic/util/strings/DiffHighlighting.java new file mode 100644 index 000000000000..c653d86f9298 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/util/strings/DiffHighlighting.java @@ -0,0 +1,98 @@ +package net.sf.jabref.logic.util.strings; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import difflib.Delta; +import difflib.DiffUtils; + +public class DiffHighlighting { + + private static final String ADDITION_START = ""; + private static final String REMOVAL_START = ""; + private static final String CHANGE_START = ""; + private static final String TAG_END = ""; + + public static String generateDiffHighlighting(String baseString, String modifiedString, String separator) { + Objects.requireNonNull(separator); + if ((baseString != null) && (modifiedString != null)) { + List stringList = new ArrayList<>(Arrays.asList(baseString.split(separator))); + List> deltaList = new ArrayList<>( + DiffUtils.diff(stringList, Arrays.asList(modifiedString.split(separator))).getDeltas()); + Collections.reverse(deltaList); + for (Delta delta : deltaList) { + int startPos = delta.getOriginal().getPosition(); + List lines = delta.getOriginal().getLines(); + int offset = 0; + switch (delta.getType()) { + case CHANGE: + for (String line : lines) { + stringList.set(startPos + offset, (offset == 0 ? DiffHighlighting.REMOVAL_START : "") + line); + offset++; + } + stringList.set((startPos + offset) - 1, + stringList.get((startPos + offset) - 1) + DiffHighlighting.TAG_END + separator + DiffHighlighting.ADDITION_START + + String.join(separator, delta.getRevised().getLines()) + DiffHighlighting.TAG_END); + break; + case DELETE: + for (String line : lines) { + stringList.set(startPos + offset, (offset == 0 ? DiffHighlighting.REMOVAL_START : "") + line); + offset++; + } + stringList.set((startPos + offset) - 1, + stringList.get((startPos + offset) - 1) + DiffHighlighting.TAG_END); + break; + case INSERT: + stringList.add(delta.getOriginal().getPosition(), + DiffHighlighting.ADDITION_START + String.join(separator, delta.getRevised().getLines()) + DiffHighlighting.TAG_END); + break; + default: + break; + } + } + return String.join(separator, stringList); + } + return modifiedString; + } + + public static String generateSymmetricHighlighting(String baseString, String modifiedString, String separator) { + if ((baseString != null) && (modifiedString != null)) { + List stringList = new ArrayList<>(Arrays.asList(baseString.split(separator))); + List> deltaList = new ArrayList<>(DiffUtils + .diff(stringList, new ArrayList<>(Arrays.asList(modifiedString.split(separator)))).getDeltas()); + Collections.reverse(deltaList); + for (Delta delta : deltaList) { + int startPos = delta.getOriginal().getPosition(); + List lines = delta.getOriginal().getLines(); + int offset = 0; + switch (delta.getType()) { + case CHANGE: + for (String line : lines) { + stringList.set(startPos + offset, (offset == 0 ? DiffHighlighting.CHANGE_START : "") + line); + offset++; + } + stringList.set((startPos + offset) - 1, stringList.get((startPos + offset) - 1) + DiffHighlighting.TAG_END); + break; + case DELETE: + for (String line : lines) { + stringList.set(startPos + offset, (offset == 0 ? DiffHighlighting.ADDITION_START : "") + line); + offset++; + } + stringList.set((startPos + offset) - 1, stringList.get((startPos + offset) - 1) + DiffHighlighting.TAG_END); + break; + case INSERT: + break; + default: + break; + } + } + return String.join(separator, stringList); + } + return modifiedString; + } + + +} diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index 4db5e2036d28..18e6afed685a 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -50,6 +50,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; import com.google.common.eventbus.EventBus; @@ -127,7 +128,7 @@ public Set getAllVisibleFields() { } Set toberemoved = new TreeSet<>(); for (String field : allFields) { - if (field.startsWith("__")) { + if (InternalBibtexFields.isInternalField(field)) { toberemoved.add(field); } } diff --git a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index c7c9d353337c..f95f6c536f84 100644 --- a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -423,6 +423,10 @@ public static boolean isNumeric(String field) { return sField.isPresent() && sField.get().isNumeric(); } + public static boolean isInternalField(String field) { + return field.startsWith("__"); + } + /** * returns a List with all fieldnames */ diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 9105603bb4f3..4dec88144f5f 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1346,7 +1346,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Changed_type_to_'%0'_for=Ændrede_type_til_'%0'_for diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 6bdc28a96ada..43e0ce879f46 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2055,7 +2055,6 @@ Original_entry=Originaleintrag Replace_original_entry=Ersetze_Originaleintrag Right_entry=Rechter_Eintrag Select_at_least_one_entry_to_manage_keywords.=Es_muss_mindestens_ein_Eintrag_ausgewählt_sein_um_Stichworte_verwalten_zu_können. -Select_one_entry.=Wählen_Sie_einen_Eintrag. Updated_entry_with_info_from_DOI=Eintrag_wurde_mit_DOI-Information_aktualisiert. Use=Benutze Changed_type_to_'%0'_for=Typ_geändert_zu_'%0'_für diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index c247bab1e772..12ac8522ff7d 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1955,7 +1955,6 @@ Left_entry=Left_entry Right_entry=Right_entry Use=Use Merge_entry_with_DOI_information=Merge_entry_with_DOI_information -Select_one_entry.=Select_one_entry. Fetching_info_based_on_DOI=Fetching_info_based_on_DOI Cannot_get_info_based_on_given_DOI\:_%0=Cannot_get_info_based_on_given_DOI\:_%0 Opening_dialog=Opening_dialog diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index d7165e77875e..63cab8f118ad 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1247,7 +1247,6 @@ Original_entry=Entrada_original Replace_original_entry=Reemplazar_entrada_original Right_entry=Entrada_derecha Select_at_least_one_entry_to_manage_keywords.=Seleccionar_al_menos_una_entrada_para_gestionar_palabras_clave. -Select_one_entry.=Seleccionar_una_entrada Updated_entry_with_info_from_DOI=Entrada_actualizada_con_información_del_DOI Use=Usar Changed_type_to_'%0'_for=Tipo_cambiado_a_'%0'_para diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 29719dc6f9fc..b8e1a33a40ee 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2009,7 +2009,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Changed_type_to_'%0'_for= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 832d2df3c79d..aba12d64823f 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1288,7 +1288,6 @@ Original_entry=Entrée_d'origine Replace_original_entry=Remplacer_l'entrée_d'origine Right_entry=Entrée_de_droite Select_at_least_one_entry_to_manage_keywords.=Sélectionner_au_moins_une_entrée_pour_gérer_les_mots-clefs. -Select_one_entry.=Sélectionner_une_entrée. Updated_entry_with_info_from_DOI=Entrée_mise_à_jour_à_partir_des_informations_du_DOI Use=Utilisation Changed_type_to_'%0'_for=Type_modifié_en_'%0'_pour diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 41af879c375c..6569ed22c766 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1264,7 +1264,6 @@ Original_entry=Entri_asli Replace_original_entry=Ganti_entri_asli Right_entry= Select_at_least_one_entry_to_manage_keywords.=Pilih_paling_sedikit_sebuah_entri_untuk_mengatur_katakunci. -Select_one_entry.=Pilih_sebuah_entri. Updated_entry_with_info_from_DOI=Entri_diperbarui_dengan_informasi_dari_DOI Use= Changed_type_to_'%0'_for=Merubah_tipe_ke_'%0'_untuk diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index bf6248f74b9f..3764196d33fd 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1365,7 +1365,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Changed_type_to_'%0'_for=Tipo_cambiato_in_'%0'_per diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 5f5d86e9cb21..02947a65c639 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2036,7 +2036,6 @@ Original_entry=元の項目 Replace_original_entry=元の項目を置き換える Right_entry=右の項目 Select_at_least_one_entry_to_manage_keywords.=キーワードを操作するには少なくともひとつの項目を選択してください。 -Select_one_entry.=1項目を選択してください。 Updated_entry_with_info_from_DOI=DOIからの情報で項目を更新しました Use=右記を使用してください: Changed_type_to_'%0'_for=右記を「%0」型に変更しました; diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 56f8527cfa73..774ff9b0a7d8 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2037,7 +2037,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Changed_type_to_'%0'_for=Type_gewijzigd_naar_'%0'_voor diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 3cb27e1d49cc..38a65da7b274 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2433,7 +2433,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Could_not_save_file.= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 3a79db535fac..71dd268b4fbd 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1262,7 +1262,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Changed_type_to_'%0'_for=Tipo_modificado_para_'%0'_para diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 8ed900dcb23e..0a2a26969746 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2008,7 +2008,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Changed_type_to_'%0'_for=Тип_с_изменением_на_'%0'_для diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index c1cba58e6ca8..370b53f700eb 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1039,7 +1039,6 @@ Select_file_from_ZIP-archive=Välj_fil_från_Zip-arkiv Select_file_type\:=Välj_filtyp\: Select_files=Välj_filer Select_new_ImportFormat_subclass= -Select_one_entry.=Välj_en_post. Select_style=Välj_stil Select_target_SQL_database\:= Select_the_tree_nodes_to_view_and_accept_or_reject_changes= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index cafab5da9767..6db3d61b7e2f 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1280,7 +1280,6 @@ Opening_dialog=İletişim_kutusu_açılıyor Original_entry=Orjinal_girdi Right_entry=Sağ_girdi Select_at_least_one_entry_to_manage_keywords.=Anahtar_sözcükleri_yönetmek_için_en_az_bir_girdi_seçiniz. -Select_one_entry.=Bir_girdi_seçiniz. Updated_entry_with_info_from_DOI=DOI'den_edinilen_bilgiyle_girdi_güncellendi Use=Kullan Changed_type_to_'%0'_for=Tür_'%0'e_değiştirildi diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index a5795fd668de..cdd8a3858184 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2029,7 +2029,6 @@ No_information_added= Original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.= -Select_one_entry.= Updated_entry_with_info_from_DOI= Use= Changed_type_to_'%0'_for=Kiểu_được_đổi_thành_'%0'_dùng_cho diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 91bbb8397f8b..30d7b51bd6a8 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1339,7 +1339,6 @@ Original_entry= Replace_original_entry= Right_entry= Select_at_least_one_entry_to_manage_keywords.=选中至少一条记录来管理关键字. -Select_one_entry.=选择一条记录. Updated_entry_with_info_from_DOI=已根据_DOI_更新记录 Use=使用 Changed_type_to_'%0'_for= diff --git a/src/test/java/net/sf/jabref/gui/mergeentries/MergeEntriesTest.java b/src/test/java/net/sf/jabref/logic/util/strings/DiffHighlightingTest.java similarity index 57% rename from src/test/java/net/sf/jabref/gui/mergeentries/MergeEntriesTest.java rename to src/test/java/net/sf/jabref/logic/util/strings/DiffHighlightingTest.java index 6a315132b53e..1ba979657bcf 100644 --- a/src/test/java/net/sf/jabref/gui/mergeentries/MergeEntriesTest.java +++ b/src/test/java/net/sf/jabref/logic/util/strings/DiffHighlightingTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.gui.mergeentries; +package net.sf.jabref.logic.util.strings; import org.junit.Test; @@ -6,76 +6,76 @@ import static org.junit.Assert.assertNull; -public class MergeEntriesTest { +public class DiffHighlightingTest { @Test public void testGenerateDiffHighlightingBothNullReturnsNull() { - assertNull(MergeEntries.generateDiffHighlighting(null, null, "")); + assertNull(DiffHighlighting.generateDiffHighlighting(null, null, "")); } @Test(expected = NullPointerException.class) public void testNullSeparatorThrowsNPE() { - assertNull(MergeEntries.generateDiffHighlighting("", "", null)); + assertNull(DiffHighlighting.generateDiffHighlighting("", "", null)); } @Test public void testGenerateDiffHighlightingNoDiff() { - assertEquals("foo", MergeEntries.generateDiffHighlighting("foo", "foo", "")); + assertEquals("foo", DiffHighlighting.generateDiffHighlighting("foo", "foo", "")); } @Test public void testGenerateDiffHighlightingSingleWordAddTextWordDiff() { assertEquals("foo foobar", - MergeEntries.generateDiffHighlighting("foo", "foobar", " ")); + DiffHighlighting.generateDiffHighlighting("foo", "foobar", " ")); } @Test public void testGenerateDiffHighlightingSingleWordAddTextCharacterDiff() { - assertEquals("foobar", MergeEntries.generateDiffHighlighting("foo", "foobar", "")); + assertEquals("foobar", DiffHighlighting.generateDiffHighlighting("foo", "foobar", "")); } @Test public void testGenerateDiffHighlightingSingleWordDeleteTextWordDiff() { assertEquals("foobar foo", - MergeEntries.generateDiffHighlighting("foobar", "foo", " ")); + DiffHighlighting.generateDiffHighlighting("foobar", "foo", " ")); } @Test public void testGenerateDiffHighlightingSingleWordDeleteTextCharacterDiff() { - assertEquals("foobar", MergeEntries.generateDiffHighlighting("foobar", "foo", "")); + assertEquals("foobar", DiffHighlighting.generateDiffHighlighting("foobar", "foo", "")); } @Test public void generateSymmetricHighlightingSingleWordAddTextWordDiff() { assertEquals("foo", - MergeEntries.generateSymmetricHighlighting("foo", "foobar", " ")); + DiffHighlighting.generateSymmetricHighlighting("foo", "foobar", " ")); } @Test public void generateSymmetricHighlightingSingleWordAddTextCharacterDiff() { - assertEquals("foo", MergeEntries.generateSymmetricHighlighting("foo", "foobar", "")); + assertEquals("foo", DiffHighlighting.generateSymmetricHighlighting("foo", "foobar", "")); } @Test public void generateSymmetricHighlightingSingleWordDeleteTextWordDiff() { assertEquals("foobar", - MergeEntries.generateSymmetricHighlighting("foobar", "foo", " ")); + DiffHighlighting.generateSymmetricHighlighting("foobar", "foo", " ")); } @Test public void generateSymmetricHighlightingSingleWordDeleteTextCharacterDiff() { - assertEquals("foobar", MergeEntries.generateSymmetricHighlighting("foobar", "foo", "")); + assertEquals("foobar", DiffHighlighting.generateSymmetricHighlighting("foobar", "foo", "")); } @Test public void generateSymmetricHighlightingMultipleWordsDeleteTextCharacterDiff() { assertEquals("foobar and something", - MergeEntries.generateSymmetricHighlighting("foobar and something", "foo and thing", "")); + DiffHighlighting.generateSymmetricHighlighting("foobar and something", "foo and thing", "")); } @Test public void generateSymmetricHighlightingMultipleWordsDeleteTextWordDiff() { assertEquals("foo bar and some thing", - MergeEntries.generateSymmetricHighlighting("foo bar and some thing", "foo and thing", " ")); + DiffHighlighting.generateSymmetricHighlighting("foo bar and some thing", "foo and thing", " ")); } } From aa721f003e54dfdb7e407444354560ed6cedefce Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 15 Jul 2016 10:21:57 +0200 Subject: [PATCH 233/268] Updated versions of test dependencies (#1585) --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f51f2c41d275..c1d692f4009d 100644 --- a/build.gradle +++ b/build.gradle @@ -115,8 +115,8 @@ dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' - testCompile 'com.github.tomakehurst:wiremock:1.58' - testCompile 'org.assertj:assertj-swing-junit:3.3.0' + testCompile 'com.github.tomakehurst:wiremock:2.1.6' + testCompile 'org.assertj:assertj-swing-junit:3.4.0' } sourceSets { From cb2cde27f91e3e5b1697b0dbf197732e86f46de9 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 15 Jul 2016 10:22:56 +0200 Subject: [PATCH 234/268] Added layout DateFormatter, see #1249 (#1584) * Added layout DateFormatter, see #1249 * Removed comment (sorry about that) --- CHANGELOG.md | 1 + .../logic/layout/format/DateFormatter.java | 26 +++++++++++++++++ .../layout/format/DateFormatterTest.java | 29 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/main/java/net/sf/jabref/logic/layout/format/DateFormatter.java create mode 100644 src/test/java/net/sf/jabref/logic/layout/format/DateFormatterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index fd5b435c1162..3e509fb999a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Changed - [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings +- [#1249](https://github.com/JabRef/jabref/issues/1249) Date layout formatter added ### Fixed - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly diff --git a/src/main/java/net/sf/jabref/logic/layout/format/DateFormatter.java b/src/main/java/net/sf/jabref/logic/layout/format/DateFormatter.java new file mode 100644 index 000000000000..5282c55fd527 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/layout/format/DateFormatter.java @@ -0,0 +1,26 @@ +package net.sf.jabref.logic.layout.format; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +import net.sf.jabref.logic.layout.ParamLayoutFormatter; + + +public class DateFormatter implements ParamLayoutFormatter { + + private String formatString = "yyyy-MM-dd"; // Use ISO-format as default + + + @Override + public String format(String fieldText) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatString); + LocalDate date = LocalDate.parse(fieldText, DateTimeFormatter.ISO_LOCAL_DATE); + return date.format(formatter); + } + + @Override + public void setArgument(String arg) { + formatString = arg; + } + +} diff --git a/src/test/java/net/sf/jabref/logic/layout/format/DateFormatterTest.java b/src/test/java/net/sf/jabref/logic/layout/format/DateFormatterTest.java new file mode 100644 index 000000000000..fe67f1a5a5f5 --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/layout/format/DateFormatterTest.java @@ -0,0 +1,29 @@ +package net.sf.jabref.logic.layout.format; + +import net.sf.jabref.logic.layout.ParamLayoutFormatter; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class DateFormatterTest { + + private ParamLayoutFormatter formatter; + + @Before + public void setUp() { + formatter = new DateFormatter(); + } + + @Test + public void testDefaultFormat() { + Assert.assertEquals("2016-07-15", formatter.format("2016-07-15")); + } + + @Test + public void testRequestedFormat() { + formatter.setArgument("MM/yyyy"); + Assert.assertEquals("07/2016", formatter.format("2016-07-15")); + } + +} From 17a679c46e26b627cd4fb5a6e53d21db3bf601ff Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 15 Jul 2016 10:24:44 +0200 Subject: [PATCH 235/268] Fixed indent --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c1d692f4009d..fb8046e13c05 100644 --- a/build.gradle +++ b/build.gradle @@ -116,7 +116,7 @@ dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' testCompile 'com.github.tomakehurst:wiremock:2.1.6' - testCompile 'org.assertj:assertj-swing-junit:3.4.0' + testCompile 'org.assertj:assertj-swing-junit:3.4.0' } sourceSets { From f97c89c1f2cc407d6975f2619f24dd1d37224b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lenhard?= Date: Fri, 15 Jul 2016 16:42:43 +0200 Subject: [PATCH 236/268] Move bst package to logic (#1587) * Move bst package into logic * Set new location of bst package for antlr * Add changelog entry * Reformulate changelog entry --- CHANGELOG.md | 1 + build.gradle | 6 +++--- src/main/antlr3/net/sf/jabref/bst/Bst.g | 4 ++-- .../sf/jabref/{ => logic}/bst/BibtexCaseChanger.java | 2 +- .../sf/jabref/{ => logic}/bst/BibtexNameFormatter.java | 2 +- .../net/sf/jabref/{ => logic}/bst/BibtexPurify.java | 2 +- .../sf/jabref/{ => logic}/bst/BibtexTextPrefix.java | 2 +- .../net/sf/jabref/{ => logic}/bst/BibtexWidth.java | 2 +- .../sf/jabref/{ => logic}/bst/ChangeCaseFunction.java | 8 ++++---- .../sf/jabref/{ => logic}/bst/FormatNameFunction.java | 6 +++--- .../net/sf/jabref/{ => logic}/bst/PurifyFunction.java | 6 +++--- .../sf/jabref/{ => logic}/bst/TextPrefixFunction.java | 6 +++--- src/main/java/net/sf/jabref/{ => logic}/bst/VM.java | 2 +- .../net/sf/jabref/{ => logic}/bst/VMException.java | 2 +- src/main/java/net/sf/jabref/{ => logic}/bst/Warn.java | 2 +- .../net/sf/jabref/{ => logic}/bst/WidthFunction.java | 6 +++--- .../sf/jabref/logic/layout/format/NameFormatter.java | 2 +- .../jabref/{ => logic}/bst/BibtexCaseChangersTest.java | 4 ++-- .../{ => logic}/bst/BibtexNameFormatterTest.java | 2 +- .../sf/jabref/{ => logic}/bst/BibtexPurifyTest.java | 2 +- .../net/sf/jabref/{ => logic}/bst/BibtexWidthTest.java | 2 +- .../java/net/sf/jabref/{ => logic}/bst/TestVM.java | 10 +++++----- .../jabref/{ => logic}/bst/TextPrefixFunctionTest.java | 2 +- .../resources/net/sf/jabref/{ => logic}/bst/abbrv.bst | 0 24 files changed, 42 insertions(+), 41 deletions(-) rename src/main/java/net/sf/jabref/{ => logic}/bst/BibtexCaseChanger.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/bst/BibtexNameFormatter.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/bst/BibtexPurify.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/bst/BibtexTextPrefix.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/bst/BibtexWidth.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/bst/ChangeCaseFunction.java (94%) rename src/main/java/net/sf/jabref/{ => logic}/bst/FormatNameFunction.java (95%) rename src/main/java/net/sf/jabref/{ => logic}/bst/PurifyFunction.java (93%) rename src/main/java/net/sf/jabref/{ => logic}/bst/TextPrefixFunction.java (95%) rename src/main/java/net/sf/jabref/{ => logic}/bst/VM.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/bst/VMException.java (96%) rename src/main/java/net/sf/jabref/{ => logic}/bst/Warn.java (96%) rename src/main/java/net/sf/jabref/{ => logic}/bst/WidthFunction.java (94%) rename src/test/java/net/sf/jabref/{ => logic}/bst/BibtexCaseChangersTest.java (98%) rename src/test/java/net/sf/jabref/{ => logic}/bst/BibtexNameFormatterTest.java (99%) rename src/test/java/net/sf/jabref/{ => logic}/bst/BibtexPurifyTest.java (96%) rename src/test/java/net/sf/jabref/{ => logic}/bst/BibtexWidthTest.java (98%) rename src/test/java/net/sf/jabref/{ => logic}/bst/TestVM.java (99%) rename src/test/java/net/sf/jabref/{ => logic}/bst/TextPrefixFunctionTest.java (96%) rename src/test/resources/net/sf/jabref/{ => logic}/bst/abbrv.bst (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e509fb999a5..2f82dcd1dd12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed +- For developers: Moved the bst package into logic. This requires the regeneration of antlr sources, execute: gradlew generateSource - [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings - [#1249](https://github.com/JabRef/jabref/issues/1249) Date layout formatter added diff --git a/build.gradle b/build.gradle index fb8046e13c05..cfdea1659bbe 100644 --- a/build.gradle +++ b/build.gradle @@ -164,12 +164,12 @@ task generateBstGrammarSource(type: JavaExec) { File antlrSource = file('src/main/antlr3/net/sf/jabref/bst/Bst.g') inputs.file antlrSource - outputs.file file('src/main/gen/net/sf/jabref/bst/BstLexer.java') - outputs.file file('src/main/gen/net/sf/jabref/bst/BstParser.java') + outputs.file file('src/main/gen/net/sf/jabref/logic/bst/BstLexer.java') + outputs.file file('src/main/gen/net/sf/jabref/logic/bst/BstParser.java') main = 'org.antlr.Tool' classpath = configurations.antlr3 - args = ["-o", file('src/main/gen/net/sf/jabref/bst/'), antlrSource] + args = ["-o", file('src/main/gen/net/sf/jabref/logic/bst/'), antlrSource] } task generateSearchGrammarSource(type: JavaExec) { diff --git a/src/main/antlr3/net/sf/jabref/bst/Bst.g b/src/main/antlr3/net/sf/jabref/bst/Bst.g index 9784d9f86a8b..bcfd1d305d2b 100644 --- a/src/main/antlr3/net/sf/jabref/bst/Bst.g +++ b/src/main/antlr3/net/sf/jabref/bst/Bst.g @@ -13,11 +13,11 @@ tokens { // applies only to the parser: @header {// Generated by ANTLR -package net.sf.jabref.bst;} +package net.sf.jabref.logic.bst;} // applies only to the lexer: @lexer::header {// Generated by ANTLR -package net.sf.jabref.bst;} +package net.sf.jabref.logic.bst;} program : commands+ -> ^(COMMANDS commands+); diff --git a/src/main/java/net/sf/jabref/bst/BibtexCaseChanger.java b/src/main/java/net/sf/jabref/logic/bst/BibtexCaseChanger.java similarity index 99% rename from src/main/java/net/sf/jabref/bst/BibtexCaseChanger.java rename to src/main/java/net/sf/jabref/logic/bst/BibtexCaseChanger.java index 33784b7d60f5..5f4deaaae67f 100644 --- a/src/main/java/net/sf/jabref/bst/BibtexCaseChanger.java +++ b/src/main/java/net/sf/jabref/logic/bst/BibtexCaseChanger.java @@ -13,7 +13,7 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.util.Optional; diff --git a/src/main/java/net/sf/jabref/bst/BibtexNameFormatter.java b/src/main/java/net/sf/jabref/logic/bst/BibtexNameFormatter.java similarity index 99% rename from src/main/java/net/sf/jabref/bst/BibtexNameFormatter.java rename to src/main/java/net/sf/jabref/logic/bst/BibtexNameFormatter.java index 5fe2f2d2c61c..33408aed066f 100644 --- a/src/main/java/net/sf/jabref/bst/BibtexNameFormatter.java +++ b/src/main/java/net/sf/jabref/logic/bst/BibtexNameFormatter.java @@ -13,7 +13,7 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.util.Arrays; import java.util.stream.Collectors; diff --git a/src/main/java/net/sf/jabref/bst/BibtexPurify.java b/src/main/java/net/sf/jabref/logic/bst/BibtexPurify.java similarity index 99% rename from src/main/java/net/sf/jabref/bst/BibtexPurify.java rename to src/main/java/net/sf/jabref/logic/bst/BibtexPurify.java index c01841579767..6d231c6a26ff 100644 --- a/src/main/java/net/sf/jabref/bst/BibtexPurify.java +++ b/src/main/java/net/sf/jabref/logic/bst/BibtexPurify.java @@ -14,7 +14,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // $Id$ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; /** * diff --git a/src/main/java/net/sf/jabref/bst/BibtexTextPrefix.java b/src/main/java/net/sf/jabref/logic/bst/BibtexTextPrefix.java similarity index 98% rename from src/main/java/net/sf/jabref/bst/BibtexTextPrefix.java rename to src/main/java/net/sf/jabref/logic/bst/BibtexTextPrefix.java index be7cddaa0bda..60820ff82303 100644 --- a/src/main/java/net/sf/jabref/bst/BibtexTextPrefix.java +++ b/src/main/java/net/sf/jabref/logic/bst/BibtexTextPrefix.java @@ -14,7 +14,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // $Id$ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; /** * The |built_in| function {\.{text.prefix\$}} pops the top two literals (the diff --git a/src/main/java/net/sf/jabref/bst/BibtexWidth.java b/src/main/java/net/sf/jabref/logic/bst/BibtexWidth.java similarity index 99% rename from src/main/java/net/sf/jabref/bst/BibtexWidth.java rename to src/main/java/net/sf/jabref/logic/bst/BibtexWidth.java index f50904bcc647..19ad61eb126c 100644 --- a/src/main/java/net/sf/jabref/bst/BibtexWidth.java +++ b/src/main/java/net/sf/jabref/logic/bst/BibtexWidth.java @@ -14,7 +14,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // $Id$ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/bst/ChangeCaseFunction.java b/src/main/java/net/sf/jabref/logic/bst/ChangeCaseFunction.java similarity index 94% rename from src/main/java/net/sf/jabref/bst/ChangeCaseFunction.java rename to src/main/java/net/sf/jabref/logic/bst/ChangeCaseFunction.java index b46e962ac745..86ec3fa0950c 100644 --- a/src/main/java/net/sf/jabref/bst/ChangeCaseFunction.java +++ b/src/main/java/net/sf/jabref/logic/bst/ChangeCaseFunction.java @@ -13,13 +13,13 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.util.Stack; -import net.sf.jabref.bst.BibtexCaseChanger.FORMAT_MODE; -import net.sf.jabref.bst.VM.BstEntry; -import net.sf.jabref.bst.VM.BstFunction; +import net.sf.jabref.logic.bst.BibtexCaseChanger.FORMAT_MODE; +import net.sf.jabref.logic.bst.VM.BstEntry; +import net.sf.jabref.logic.bst.VM.BstFunction; /** * From the Bibtex manual: diff --git a/src/main/java/net/sf/jabref/bst/FormatNameFunction.java b/src/main/java/net/sf/jabref/logic/bst/FormatNameFunction.java similarity index 95% rename from src/main/java/net/sf/jabref/bst/FormatNameFunction.java rename to src/main/java/net/sf/jabref/logic/bst/FormatNameFunction.java index 9a58ea6221d6..6f81677f1c02 100644 --- a/src/main/java/net/sf/jabref/bst/FormatNameFunction.java +++ b/src/main/java/net/sf/jabref/logic/bst/FormatNameFunction.java @@ -13,12 +13,12 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.util.Stack; -import net.sf.jabref.bst.VM.BstEntry; -import net.sf.jabref.bst.VM.BstFunction; +import net.sf.jabref.logic.bst.VM.BstEntry; +import net.sf.jabref.logic.bst.VM.BstFunction; import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; diff --git a/src/main/java/net/sf/jabref/bst/PurifyFunction.java b/src/main/java/net/sf/jabref/logic/bst/PurifyFunction.java similarity index 93% rename from src/main/java/net/sf/jabref/bst/PurifyFunction.java rename to src/main/java/net/sf/jabref/logic/bst/PurifyFunction.java index f6765e8a61da..f5ca1f342197 100644 --- a/src/main/java/net/sf/jabref/bst/PurifyFunction.java +++ b/src/main/java/net/sf/jabref/logic/bst/PurifyFunction.java @@ -13,12 +13,12 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.util.Stack; -import net.sf.jabref.bst.VM.BstEntry; -import net.sf.jabref.bst.VM.BstFunction; +import net.sf.jabref.logic.bst.VM.BstEntry; +import net.sf.jabref.logic.bst.VM.BstFunction; /** * diff --git a/src/main/java/net/sf/jabref/bst/TextPrefixFunction.java b/src/main/java/net/sf/jabref/logic/bst/TextPrefixFunction.java similarity index 95% rename from src/main/java/net/sf/jabref/bst/TextPrefixFunction.java rename to src/main/java/net/sf/jabref/logic/bst/TextPrefixFunction.java index 9b10d34ed95a..910041d73a01 100644 --- a/src/main/java/net/sf/jabref/bst/TextPrefixFunction.java +++ b/src/main/java/net/sf/jabref/logic/bst/TextPrefixFunction.java @@ -13,12 +13,12 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.util.Stack; -import net.sf.jabref.bst.VM.BstEntry; -import net.sf.jabref.bst.VM.BstFunction; +import net.sf.jabref.logic.bst.VM.BstEntry; +import net.sf.jabref.logic.bst.VM.BstFunction; /** The |built_in| function {\.{text.prefix\$}} pops the top two literals diff --git a/src/main/java/net/sf/jabref/bst/VM.java b/src/main/java/net/sf/jabref/logic/bst/VM.java similarity index 99% rename from src/main/java/net/sf/jabref/bst/VM.java rename to src/main/java/net/sf/jabref/logic/bst/VM.java index 0d97dd27bbd2..a5722551a461 100644 --- a/src/main/java/net/sf/jabref/bst/VM.java +++ b/src/main/java/net/sf/jabref/logic/bst/VM.java @@ -13,7 +13,7 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.io.File; import java.io.IOException; diff --git a/src/main/java/net/sf/jabref/bst/VMException.java b/src/main/java/net/sf/jabref/logic/bst/VMException.java similarity index 96% rename from src/main/java/net/sf/jabref/bst/VMException.java rename to src/main/java/net/sf/jabref/logic/bst/VMException.java index 5fada27bed96..7d6ca86d0895 100644 --- a/src/main/java/net/sf/jabref/bst/VMException.java +++ b/src/main/java/net/sf/jabref/logic/bst/VMException.java @@ -13,7 +13,7 @@ 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.bst; +package net.sf.jabref.logic.bst; public class VMException extends RuntimeException { diff --git a/src/main/java/net/sf/jabref/bst/Warn.java b/src/main/java/net/sf/jabref/logic/bst/Warn.java similarity index 96% rename from src/main/java/net/sf/jabref/bst/Warn.java rename to src/main/java/net/sf/jabref/logic/bst/Warn.java index 6af03a7fca7a..98f095ab3220 100644 --- a/src/main/java/net/sf/jabref/bst/Warn.java +++ b/src/main/java/net/sf/jabref/logic/bst/Warn.java @@ -13,7 +13,7 @@ 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.bst; +package net.sf.jabref.logic.bst; @FunctionalInterface public interface Warn { diff --git a/src/main/java/net/sf/jabref/bst/WidthFunction.java b/src/main/java/net/sf/jabref/logic/bst/WidthFunction.java similarity index 94% rename from src/main/java/net/sf/jabref/bst/WidthFunction.java rename to src/main/java/net/sf/jabref/logic/bst/WidthFunction.java index 1b23a65794d9..35b5da295f17 100644 --- a/src/main/java/net/sf/jabref/bst/WidthFunction.java +++ b/src/main/java/net/sf/jabref/logic/bst/WidthFunction.java @@ -13,12 +13,12 @@ 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.bst; +package net.sf.jabref.logic.bst; import java.util.Stack; -import net.sf.jabref.bst.VM.BstEntry; -import net.sf.jabref.bst.VM.BstFunction; +import net.sf.jabref.logic.bst.VM.BstEntry; +import net.sf.jabref.logic.bst.VM.BstFunction; /** * The |built_in| function {\.{width\$}} pops the top (string) literal and diff --git a/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java index e1abc5913a12..5f7812876622 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java @@ -20,7 +20,7 @@ import java.util.Map; import net.sf.jabref.Globals; -import net.sf.jabref.bst.BibtexNameFormatter; +import net.sf.jabref.logic.bst.BibtexNameFormatter; import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.model.entry.AuthorList; diff --git a/src/test/java/net/sf/jabref/bst/BibtexCaseChangersTest.java b/src/test/java/net/sf/jabref/logic/bst/BibtexCaseChangersTest.java similarity index 98% rename from src/test/java/net/sf/jabref/bst/BibtexCaseChangersTest.java rename to src/test/java/net/sf/jabref/logic/bst/BibtexCaseChangersTest.java index 262015e52f8f..b1388de694a1 100644 --- a/src/test/java/net/sf/jabref/bst/BibtexCaseChangersTest.java +++ b/src/test/java/net/sf/jabref/logic/bst/BibtexCaseChangersTest.java @@ -1,6 +1,6 @@ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; -import net.sf.jabref.bst.BibtexCaseChanger.FORMAT_MODE; +import net.sf.jabref.logic.bst.BibtexCaseChanger.FORMAT_MODE; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/bst/BibtexNameFormatterTest.java b/src/test/java/net/sf/jabref/logic/bst/BibtexNameFormatterTest.java similarity index 99% rename from src/test/java/net/sf/jabref/bst/BibtexNameFormatterTest.java rename to src/test/java/net/sf/jabref/logic/bst/BibtexNameFormatterTest.java index 01b74739fc6e..56100dd3cd68 100644 --- a/src/test/java/net/sf/jabref/bst/BibtexNameFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/bst/BibtexNameFormatterTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; import net.sf.jabref.model.entry.AuthorList; diff --git a/src/test/java/net/sf/jabref/bst/BibtexPurifyTest.java b/src/test/java/net/sf/jabref/logic/bst/BibtexPurifyTest.java similarity index 96% rename from src/test/java/net/sf/jabref/bst/BibtexPurifyTest.java rename to src/test/java/net/sf/jabref/logic/bst/BibtexPurifyTest.java index 95756761c9f3..48ea2d915dcb 100644 --- a/src/test/java/net/sf/jabref/bst/BibtexPurifyTest.java +++ b/src/test/java/net/sf/jabref/logic/bst/BibtexPurifyTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/bst/BibtexWidthTest.java b/src/test/java/net/sf/jabref/logic/bst/BibtexWidthTest.java similarity index 98% rename from src/test/java/net/sf/jabref/bst/BibtexWidthTest.java rename to src/test/java/net/sf/jabref/logic/bst/BibtexWidthTest.java index 1f42d01f37a4..c14533c5bcd4 100644 --- a/src/test/java/net/sf/jabref/bst/BibtexWidthTest.java +++ b/src/test/java/net/sf/jabref/logic/bst/BibtexWidthTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/bst/TestVM.java b/src/test/java/net/sf/jabref/logic/bst/TestVM.java similarity index 99% rename from src/test/java/net/sf/jabref/bst/TestVM.java rename to src/test/java/net/sf/jabref/logic/bst/TestVM.java index 0f1286d28d25..a63da63f73b0 100644 --- a/src/test/java/net/sf/jabref/bst/TestVM.java +++ b/src/test/java/net/sf/jabref/logic/bst/TestVM.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; import java.io.File; import java.io.IOException; @@ -9,10 +9,10 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.bst.VM.BstEntry; -import net.sf.jabref.bst.VM.StackFunction; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.bst.VM.BstEntry; +import net.sf.jabref.logic.bst.VM.StackFunction; import net.sf.jabref.model.entry.BibEntry; import org.antlr.runtime.RecognitionException; @@ -30,7 +30,7 @@ public void setPreferences() { @Test public void testAbbrv() throws RecognitionException, IOException { - VM vm = new VM(new File("src/test/resources/net/sf/jabref/bst/abbrv.bst")); + VM vm = new VM(new File("src/test/resources/net/sf/jabref/logic/bst/abbrv.bst")); List v = new ArrayList<>(); v.add(t1BibtexEntry()); @@ -664,7 +664,7 @@ private String t1BibtexString() { @Test public void testHypthenatedName() throws RecognitionException, IOException { - VM vm = new VM(new File("src/test/resources/net/sf/jabref/bst/abbrv.bst")); + VM vm = new VM(new File("src/test/resources/net/sf/jabref/logic/bst/abbrv.bst")); List v = new ArrayList<>(); v.add(TestVM.bibtexString2BibtexEntry("@article{canh05, author = \"Jean-Paul Sartre\" }")); Assert.assertTrue(vm.run(v).contains("J.-P. Sartre")); diff --git a/src/test/java/net/sf/jabref/bst/TextPrefixFunctionTest.java b/src/test/java/net/sf/jabref/logic/bst/TextPrefixFunctionTest.java similarity index 96% rename from src/test/java/net/sf/jabref/bst/TextPrefixFunctionTest.java rename to src/test/java/net/sf/jabref/logic/bst/TextPrefixFunctionTest.java index d24601cf6ef2..02c908b5a2dc 100644 --- a/src/test/java/net/sf/jabref/bst/TextPrefixFunctionTest.java +++ b/src/test/java/net/sf/jabref/logic/bst/TextPrefixFunctionTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.bst; +package net.sf.jabref.logic.bst; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/resources/net/sf/jabref/bst/abbrv.bst b/src/test/resources/net/sf/jabref/logic/bst/abbrv.bst similarity index 100% rename from src/test/resources/net/sf/jabref/bst/abbrv.bst rename to src/test/resources/net/sf/jabref/logic/bst/abbrv.bst From 4f1f920e973aae5c13573a2b466a1e4304929582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lenhard?= Date: Fri, 15 Jul 2016 16:58:49 +0200 Subject: [PATCH 237/268] Implement 1516 (#1589) Display selected field names in uppercase * Uppercase selected field names in the entry editor * Added changelog entry * Use consistent code structure * Remove unused imports * Include ISRN in selected terms for upper casing --- CHANGELOG.md | 1 + .../gui/fieldeditors/FieldNameLabel.java | 28 ++++++++++++++++--- .../gui/fieldeditors/FileListEditor.java | 3 +- .../sf/jabref/gui/fieldeditors/TextArea.java | 3 +- .../sf/jabref/gui/fieldeditors/TextField.java | 3 +- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f82dcd1dd12..292f3c65486c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed +- [#1516](https://github.com/JabRef/jabref/issues/1516) Selected field names are written in uppercase in the entry editor - For developers: Moved the bst package into logic. This requires the regeneration of antlr sources, execute: gradlew generateSource - [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings - [#1249](https://github.com/JabRef/jabref/issues/1249) Date layout formatter added diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java b/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java index 9284eb1b51fd..142a374e5740 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java @@ -24,16 +24,15 @@ import javax.swing.SwingConstants; import net.sf.jabref.gui.GUIGlobals; +import net.sf.jabref.model.entry.EntryUtil; public class FieldNameLabel extends JLabel { public FieldNameLabel(String name) { - super(name, SwingConstants.LEFT); + super(FieldNameLabel.getFieldNameLabelText(name), SwingConstants.LEFT); + setVerticalAlignment(SwingConstants.TOP); - //setFont(GUIGlobals.fieldNameFont); setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); - // setBorder(BorderFactory.createMatteBorder(1,0,0,0, Color.GRAY)); - //setBorder(BorderFactory.createEtchedBorder()); setBorder(BorderFactory.createEmptyBorder()); } @@ -47,4 +46,25 @@ public void paintComponent(Graphics g) { super.paintComponent(g2); } + private static String getFieldNameLabelText(String fieldName) { + // selected terms should be uppercase + if("isbn".equalsIgnoreCase(fieldName)) { + return " ISBN "; + } else if ("url".equalsIgnoreCase(fieldName)){ + return " URL "; + } else if ("uri".equalsIgnoreCase(fieldName)) { + return " URI "; + } else if ("issn".equalsIgnoreCase(fieldName)) { + return " ISSN "; + } else if("doi".equalsIgnoreCase(fieldName)) { + return " DOI "; + } else if("isrn".equalsIgnoreCase(fieldName)) { + return " ISRN "; + } + + // otherwise capitalize + return ' ' + EntryUtil.capitalizeFirst(fieldName) + ' '; + } + + } diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java b/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java index 3c5ca5bf0bd3..5077520a1c72 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/FileListEditor.java @@ -69,7 +69,6 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.EntryUtil; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; @@ -100,7 +99,7 @@ public FileListEditor(JabRefFrame frame, BibDatabaseContext databaseContext, Str this.databaseContext = databaseContext; this.fieldName = fieldName; this.entryEditor = entryEditor; - label = new FieldNameLabel(" " + EntryUtil.capitalizeFirst(fieldName) + " "); + label = new FieldNameLabel(fieldName); tableModel = new FileListTableModel(); setText(content); setModel(tableModel); diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java b/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java index c22f6c7c410a..993ea1f2f68d 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/TextArea.java @@ -27,7 +27,6 @@ import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.autocompleter.AutoCompleteListener; import net.sf.jabref.gui.fieldeditors.contextmenu.FieldTextMenu; -import net.sf.jabref.model.entry.EntryUtil; /** * An implementation of the FieldEditor backed by a JTextArea. @@ -62,7 +61,7 @@ public TextArea(String fieldName, String content) { setWrapStyleWord(true); this.fieldName = fieldName; - label = new FieldNameLabel(' ' + EntryUtil.capitalizeFirst(this.fieldName) + ' '); + label = new FieldNameLabel(fieldName); setBackground(GUIGlobals.validFieldBackgroundColor); setForeground(GUIGlobals.editorTextColor); diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java b/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java index b93f474a7a37..5890f31c8d2b 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/TextField.java @@ -33,7 +33,6 @@ import net.sf.jabref.gui.actions.PasteAction; import net.sf.jabref.gui.autocompleter.AutoCompleteListener; import net.sf.jabref.gui.fieldeditors.contextmenu.FieldTextMenu; -import net.sf.jabref.model.entry.EntryUtil; /** * An implementation of the FieldEditor backed by a JTextField. Used for single-line input, only BibTex key at the @@ -63,7 +62,7 @@ public TextField(String fieldName, String content, boolean changeColorOnFocus) { addFocusListener(new FieldEditorFocusListener()); } this.fieldName = fieldName; - label = new FieldNameLabel(' ' + EntryUtil.capitalizeFirst(this.fieldName) + ' '); + label = new FieldNameLabel(this.fieldName); setBackground(GUIGlobals.validFieldBackgroundColor); setForeground(GUIGlobals.editorTextColor); From 6d658f8d3db78959daa112c81f5861a0dd460752 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 15 Jul 2016 17:41:55 +0200 Subject: [PATCH 238/268] enable slack notifications description: https://blog.travis-ci.com/2014-03-13-slack-notifications/ --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index fd3b82f02762..ed99ce56498a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,3 +63,8 @@ cache: directories: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ + +# enable slack notifications +notifications: + slack: + secure: B5LGefXS1Jt+d7tUzzmakoz+/ZnFUzmmmYuBXaikTUPDuxXacIrVTv4Vx+tcagxDrPQ3A20oi3+0t6p8xagytjLI9u3abACyWwO3+CbywuJDLBzxADVhg/+mKssfTmemRlZoBUrBlHZVk69LIJvqXFR5l5zAiBtDL1dWPeMEEvI= From 622a0da33401d102b05b8e245fd1eb7b886494ad Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sat, 16 Jul 2016 10:51:18 +0200 Subject: [PATCH 239/268] Refactor writing of bib files (#1472) * Refactor writing of bib files - Abstract class BibDatabaseWriter, which controls the generic things of writing a database (i.e. sorting entries, applying save actions, some basic conversations, ...) - Derived class BibtexDatabaseWriter, which only contains logic how to actually write to in BibTeX format (should be simple to write similar classes for other export formats like ris) - Make SaveSession abstract and introduce two implementations which write to a temporary file (FileSaveSession) or two a string/buffer (StringSaveSession) - Move code related to lock files to FileBasedLock * Incorporate feedback * Rebase --- .../net/sf/jabref/benchmarks/Benchmarks.java | 24 +- .../net/sf/jabref/cli/ArgumentProcessor.java | 10 +- .../net/sf/jabref/collab/ChangeScanner.java | 9 +- .../sf/jabref/collab/FileUpdateMonitor.java | 24 +- .../sf/jabref/exporter/AutoSaveManager.java | 4 +- .../sf/jabref/exporter/BibDatabaseWriter.java | 329 +++++++----------- .../jabref/exporter/BibtexDatabaseWriter.java | 168 +++++++++ .../net/sf/jabref/exporter/ExportFormat.java | 11 +- .../sf/jabref/exporter/FileSaveSession.java | 142 ++++++++ .../sf/jabref/exporter/MSBibExportFormat.java | 12 +- .../sf/jabref/exporter/ModsExportFormat.java | 12 +- .../jabref/exporter/SaveDatabaseAction.java | 15 +- .../net/sf/jabref/exporter/SaveException.java | 8 + .../sf/jabref/exporter/SavePreferences.java | 4 + .../net/sf/jabref/exporter/SaveSession.java | 193 ++-------- .../sf/jabref/exporter/StringSaveSession.java | 71 ++++ .../java/net/sf/jabref/gui/BasePanel.java | 11 +- .../jabref/importer/OpenDatabaseAction.java | 18 +- .../jabref/logic/util/io/FileBasedLock.java | 74 +++- .../jabref/logic/util/strings/StringUtil.java | 3 + ...est.java => BibtexDatabaseWriterTest.java} | 230 ++++++------ .../exporter/MSBibExportFormatTestFiles.java | 2 +- .../exporter/MsBibExportFormatTest.java | 2 +- src/test/resources/testbib/complex.bib | 1 + 24 files changed, 788 insertions(+), 589 deletions(-) create mode 100644 src/main/java/net/sf/jabref/exporter/BibtexDatabaseWriter.java create mode 100644 src/main/java/net/sf/jabref/exporter/FileSaveSession.java create mode 100644 src/main/java/net/sf/jabref/exporter/StringSaveSession.java rename src/test/java/net/sf/jabref/exporter/{BibDatabaseWriterTest.java => BibtexDatabaseWriterTest.java} (68%) diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index e041f7217799..2d9d5de98e44 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.io.StringReader; -import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -13,8 +12,9 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.BibDatabaseWriter; +import net.sf.jabref.exporter.BibtexDatabaseWriter; import net.sf.jabref.exporter.SavePreferences; +import net.sf.jabref.exporter.StringSaveSession; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.importer.fileformat.ParseException; @@ -45,7 +45,7 @@ public class Benchmarks { private String htmlConversionString; @Setup - public void init() throws IOException { + public void init() throws Exception { Globals.prefs = JabRefPreferences.getInstance(); Random randomizer = new Random(); @@ -60,13 +60,11 @@ public void init() throws IOException { entry.setField("rnd", "2" + randomizer.nextInt()); database.insertEntry(entry); } - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); - StringWriter stringWriter = new StringWriter(); - - databaseWriter.writePartOfDatabase(stringWriter, + BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter<>(StringSaveSession::new); + StringSaveSession saveSession = databaseWriter.savePartOfDatabase( new BibDatabaseContext(database, new MetaData(), new Defaults()), database.getEntries(), new SavePreferences()); - bibtexString = stringWriter.toString(); + bibtexString = saveSession.getStringValue(); latexConversionString = "{A} \\textbf{bold} approach {\\it to} ${{\\Sigma}}{\\Delta}$ modulator \\textsuperscript{2} \\$"; @@ -81,14 +79,12 @@ public ParserResult parse() throws IOException { } @Benchmark - public String write() throws IOException { - StringWriter stringWriter = new StringWriter(); - - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); - databaseWriter.writePartOfDatabase(stringWriter, + public String write() throws Exception { + BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter<>(StringSaveSession::new); + StringSaveSession saveSession = databaseWriter.savePartOfDatabase( new BibDatabaseContext(database, new MetaData(), new Defaults()), database.getEntries(), new SavePreferences()); - return stringWriter.toString(); + return saveSession.getStringValue(); } @Benchmark diff --git a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java index bc2abb09e9c2..9a8b0d548bd5 100644 --- a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java @@ -20,7 +20,9 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.exporter.BibDatabaseWriter; +import net.sf.jabref.exporter.BibtexDatabaseWriter; import net.sf.jabref.exporter.ExportFormats; +import net.sf.jabref.exporter.FileSaveSession; import net.sf.jabref.exporter.IExportFormat; import net.sf.jabref.exporter.SaveException; import net.sf.jabref.exporter.SavePreferences; @@ -286,7 +288,7 @@ private boolean generateAux(List loaded, String[] data) { try { System.out.println(Localization.lang("Saving") + ": " + subName); SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs); - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); + BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter(FileSaveSession::new); Defaults defaults = new Defaults(BibDatabaseMode .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); SaveSession session = databaseWriter.saveDatabase(new BibDatabaseContext(newBase, defaults), @@ -300,7 +302,7 @@ private boolean generateAux(List loaded, String[] data) { session.getEncoding().displayName()) + " " + session.getWriter().getProblemCharacters()); } - session.commit(new File(subName)); + session.commit(subName); } catch (SaveException ex) { System.err.println( Localization.lang("Could not save file.") + "\n" + ex.getLocalizedMessage()); @@ -330,7 +332,7 @@ private void exportFile(List loaded, String[] data) { SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs); Defaults defaults = new Defaults(BibDatabaseMode.fromPreference( Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); + BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter(FileSaveSession::new); SaveSession session = databaseWriter.saveDatabase( new BibDatabaseContext(pr.getDatabase(), pr.getMetaData(), defaults), prefs); @@ -342,7 +344,7 @@ private void exportFile(List loaded, String[] data) { session.getEncoding().displayName()) + " " + session.getWriter().getProblemCharacters()); } - session.commit(new File(data[0])); + session.commit(data[0]); } catch (SaveException ex) { System.err.println( Localization.lang("Could not save file.") + "\n" + ex.getLocalizedMessage()); diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index c37ce2732b7b..f9966dc085eb 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -17,6 +17,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; @@ -35,6 +36,8 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.exporter.BibDatabaseWriter; +import net.sf.jabref.exporter.BibtexDatabaseWriter; +import net.sf.jabref.exporter.FileSaveSession; import net.sf.jabref.exporter.SaveException; import net.sf.jabref.exporter.SavePreferences; import net.sf.jabref.exporter.SaveSession; @@ -95,8 +98,8 @@ public void run() { try { // Parse the temporary file. - File tempFile = Globals.getFileUpdateMonitor().getTempFile(panel.fileMonitorHandle()); - ParserResult pr = OpenDatabaseAction.loadDatabase(tempFile, Globals.prefs.getDefaultEncoding()); + Path tempFile = Globals.getFileUpdateMonitor().getTempFile(panel.fileMonitorHandle()); + ParserResult pr = OpenDatabaseAction.loadDatabase(tempFile.toFile(), Globals.prefs.getDefaultEncoding()); inTemp = pr.getDatabase(); mdInTemp = pr.getMetaData(); // Parse the modified file. @@ -164,7 +167,7 @@ private void storeTempDatabase() { Defaults defaults = new Defaults(BibDatabaseMode .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); + BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter(FileSaveSession::new); SaveSession ss = databaseWriter.saveDatabase(new BibDatabaseContext(inTemp, mdInTemp, defaults), prefs); ss.commit(Globals.getFileUpdateMonitor().getTempFile(panel.fileMonitorHandle())); } catch (SaveException ex) { diff --git a/src/main/java/net/sf/jabref/collab/FileUpdateMonitor.java b/src/main/java/net/sf/jabref/collab/FileUpdateMonitor.java index 80d0df9ba145..2a6483711929 100644 --- a/src/main/java/net/sf/jabref/collab/FileUpdateMonitor.java +++ b/src/main/java/net/sf/jabref/collab/FileUpdateMonitor.java @@ -17,6 +17,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -133,7 +135,7 @@ public void updateTimeStamp(String key) { * @throws IllegalArgumentException If the handle doesn't correspond to an entry. * @return File The temporary file. */ - public File getTempFile(String key) throws IllegalArgumentException { + public Path getTempFile(String key) throws IllegalArgumentException { Object o = entries.get(key); if (o == null) { throw new IllegalArgumentException("Entry not found"); @@ -149,7 +151,7 @@ static class Entry { private final FileUpdateListener listener; private final File file; - private final File tmpFile; + private final Path tmpFile; private long timeStamp; private long fileSize; @@ -161,7 +163,7 @@ public Entry(FileUpdateListener ul, File f) { fileSize = file.length(); tmpFile = FileUpdateMonitor.getTempFile(); if (tmpFile != null) { - tmpFile.deleteOnExit(); + tmpFile.toFile().deleteOnExit(); copy(); } } @@ -194,9 +196,9 @@ public boolean copy() { boolean res = false; try { - res = FileUtil.copyFile(file, tmpFile, true); + res = FileUtil.copyFile(file, tmpFile.toFile(), true); } catch (IOException ex) { - LOGGER.info("Cannot copy to temporary file '" + tmpFile.getPath() + '\'', ex); + LOGGER.info("Cannot copy to temporary file '" + tmpFile + '\'', ex); } return res; } @@ -218,7 +220,7 @@ public void notifyFileRemoved() { listener.fileRemoved(); } - public File getTmpFile() { + public Path getTmpFile() { return tmpFile; } @@ -228,14 +230,14 @@ public void decreaseTimeStamp() { } - private static synchronized File getTempFile() { - File f = null; + private static synchronized Path getTempFile() { + Path temporaryFile = null; try { - f = File.createTempFile("jabref", null); - f.deleteOnExit(); + temporaryFile = Files.createTempFile("jabref", null); + temporaryFile.toFile().deleteOnExit(); } catch (IOException ex) { LOGGER.warn("Could not create temporary file.", ex); } - return f; + return temporaryFile; } } diff --git a/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java b/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java index 08f5769d13cf..6e62c22d6dac 100644 --- a/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java +++ b/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java @@ -96,9 +96,9 @@ private static boolean autoSave(BasePanel panel) { .withMakeBackup(false) .withEncoding(panel.getBibDatabaseContext().getMetaData().getEncoding()); - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); + BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter(FileSaveSession::new); SaveSession ss = databaseWriter.saveDatabase(panel.getBibDatabaseContext(), prefs); - ss.commit(backupFile); + ss.commit(backupFile.toPath()); } catch (SaveException e) { LOGGER.error("Problem with automatic save", e); return false; diff --git a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java index 18ddd90a3e38..0b06ee4bb416 100644 --- a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java @@ -1,22 +1,23 @@ -/* Copyright (C) 2003-2016 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. +/* + * Copyright (C) 2003-2016 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.exporter; import java.io.IOException; -import java.io.Writer; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; @@ -33,37 +34,50 @@ import java.util.stream.Collectors; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.Globals; import net.sf.jabref.MetaData; -import net.sf.jabref.logic.bibtex.BibEntryWriter; -import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.bibtex.comparator.BibtexStringComparator; import net.sf.jabref.logic.bibtex.comparator.CrossRefEntryComparator; import net.sf.jabref.logic.bibtex.comparator.FieldComparator; import net.sf.jabref.logic.bibtex.comparator.FieldComparatorStack; import net.sf.jabref.logic.bibtex.comparator.IdComparator; import net.sf.jabref.logic.config.SaveOrderConfig; -import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryType; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class BibDatabaseWriter { +public abstract class BibDatabaseWriter { private static final Pattern REFERENCE_PATTERN = Pattern.compile("(#[A-Za-z]+#)"); // Used to detect string references in strings - private static final Log LOGGER = LogFactory.getLog(BibDatabaseWriter.class); - private static final String STRING_PREFIX = "@String"; - private static final String COMMENT_PREFIX = "@Comment"; - private static final String PREAMBLE_PREFIX = "@Preamble"; - private BibEntry exceptionCause; - private boolean isFirstStringInType; + private final SaveSessionFactory saveSessionFactory; + + private E session; + + public BibDatabaseWriter(SaveSessionFactory saveSessionFactory) { + this.saveSessionFactory = saveSessionFactory; + } + + public interface SaveSessionFactory { + E createSaveSession(Charset encoding, Boolean makeBackup) throws SaveException; + } + + private static List applySaveActions(List toChange, MetaData metaData) { + List changes = new ArrayList<>(); + + Optional saveActions = metaData.getSaveActions(); + saveActions.ifPresent(actions -> { + // save actions defined -> apply for every entry + for (BibEntry entry : toChange) { + changes.addAll(actions.applySaveActions(entry)); + } + }); + + return changes; + } private static List> getSaveComparators(SavePreferences preferences, MetaData metaData) { @@ -94,7 +108,7 @@ private static List> getSaveComparators(SavePreferences pre * and non-database save operations. In a non-database save operation * (such as the exportDatabase call), we do not wish to use the * global preference of saving in standard order. - */ + */ public static List getSortedEntries(BibDatabaseContext bibDatabaseContext, List entriesToSort, SavePreferences preferences) { Objects.requireNonNull(bibDatabaseContext); @@ -138,66 +152,41 @@ private static Optional getSaveOrder(SavePreferences preference } /** - * Saves the database to file. Two boolean values indicate whether only - * entries which are marked as search / group hit should be saved. This can be used to - * let the user save only the results of a search. False and false means all - * entries are saved. + * Saves the complete database. */ - public SaveSession saveDatabase(BibDatabaseContext bibDatabaseContext, SavePreferences preferences) + public E saveDatabase(BibDatabaseContext bibDatabaseContext, SavePreferences preferences) throws SaveException { return savePartOfDatabase(bibDatabaseContext, bibDatabaseContext.getDatabase().getEntries(), preferences); } - public SaveSession savePartOfDatabase(BibDatabaseContext bibDatabaseContext, List entries, - SavePreferences preferences) throws SaveException { - - SaveSession session; - try { - session = new SaveSession(preferences.getEncoding(), preferences.getMakeBackup()); - } catch (IOException e) { - throw new SaveException(e.getMessage(), e.getLocalizedMessage()); - } - - exceptionCause = null; - // Get our data stream. This stream writes only to a temporary file until committed. - try (VerifyingWriter writer = session.getWriter()) { - List saveActionChanges = writePartOfDatabase(writer, bibDatabaseContext, entries, preferences); - session.addFieldChanges(saveActionChanges); - } catch (IOException ex) { - LOGGER.error("Could not write file", ex); - session.cancel(); - throw new SaveException(ex.getMessage(), ex.getLocalizedMessage(), exceptionCause); - } - - return session; - - } + /** + * Saves the database, including only the specified entries. + */ + public E savePartOfDatabase(BibDatabaseContext bibDatabaseContext, + List entries, SavePreferences preferences) throws SaveException { - public List writePartOfDatabase(Writer writer, BibDatabaseContext bibDatabaseContext, - List entries, SavePreferences preferences) throws IOException { - Objects.requireNonNull(writer); + session = saveSessionFactory.createSaveSession(preferences.getEncodingOrDefault(), preferences.getMakeBackup()); // Map to collect entry type definitions that we must save along with entries using them. Map typesToWrite = new TreeMap<>(); + // Some file formats write something at the start of the file (like the encoding) if (preferences.getSaveType() != SavePreferences.DatabaseSaveType.PLAIN_BIBTEX) { - // Write signature. - writeBibFileHeader(writer, preferences.getEncoding()); + writePrelogue(bibDatabaseContext, preferences.getEncoding()); } // Write preamble if there is one. - writePreamble(writer, bibDatabaseContext.getDatabase().getPreamble()); + writePreamble(bibDatabaseContext.getDatabase().getPreamble()); // Write strings if there are any. - writeStrings(writer, bibDatabaseContext.getDatabase(), preferences.isReformatFile()); + writeStrings(bibDatabaseContext.getDatabase(), preferences.isReformatFile()); // Write database entries. - List sortedEntries = BibDatabaseWriter.getSortedEntries(bibDatabaseContext, entries, preferences); - List saveActionChanges = BibDatabaseWriter.applySaveActions(sortedEntries, bibDatabaseContext.getMetaData()); - BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new LatexFieldFormatter(), true); - for (BibEntry entry : sortedEntries) { - exceptionCause = entry; + List sortedEntries = getSortedEntries(bibDatabaseContext, entries, preferences); + List saveActionChanges = applySaveActions(sortedEntries, bibDatabaseContext.getMetaData()); + session.addFieldChanges(saveActionChanges); + for (BibEntry entry : sortedEntries) { // Check if we must write the type definition for this // entry, as well. Our criterion is that all non-standard // types (*not* all customized standard types) must be written. @@ -208,172 +197,58 @@ public List writePartOfDatabase(Writer writer, BibDatabaseContext b entryType -> typesToWrite.put(entryType.getName(), entryType)); } - bibtexEntryWriter.write(entry, writer, bibDatabaseContext.getMode(), preferences.isReformatFile()); - + writeEntry(entry, bibDatabaseContext.getMode(), preferences.isReformatFile()); } if (preferences.getSaveType() != SavePreferences.DatabaseSaveType.PLAIN_BIBTEX) { // Write meta data. - writeMetaData(writer, bibDatabaseContext.getMetaData()); + writeMetaData(bibDatabaseContext.getMetaData()); // Write type definitions, if any: - writeTypeDefinitions(writer, typesToWrite); + writeEntryTypeDefinitions(typesToWrite); } //finally write whatever remains of the file, but at least a concluding newline - writeEpilogue(writer, bibDatabaseContext.getDatabase()); - - return saveActionChanges; - } - - /** - * Saves the database to file, including only the entries included in the - * supplied input array bes. - */ - public SaveSession savePartOfDatabase(BibDatabaseContext bibDatabaseContext, SavePreferences preferences, - List entries) throws SaveException { - - return savePartOfDatabase(bibDatabaseContext, entries, preferences); - } - - private static List applySaveActions(List toChange, MetaData metaData) { - List changes = new ArrayList<>(); + writeEpilogue(bibDatabaseContext.getDatabase().getEpilog()); - Optional saveActions = metaData.getSaveActions(); - if (saveActions.isPresent()) { - // save actions defined -> apply for every entry - for (BibEntry entry : toChange) { - changes.addAll(saveActions.get().applySaveActions(entry)); - } + try { + session.getWriter().close(); + } catch (IOException e) { + throw new SaveException(e); } - - return changes; + return session; } - /** - * Writes the file encoding information. - * - * @param encoding String the name of the encoding, which is part of the file header. - */ - private void writeBibFileHeader(Writer out, Charset encoding) throws IOException { - if(encoding == null) { - return; - } + protected abstract void writePrelogue(BibDatabaseContext bibDatabaseContext, Charset encoding) throws SaveException; - out.write("% "); - out.write(Globals.ENCODING_PREFIX + encoding); - out.write(Globals.NEWLINE); - } + protected abstract void writeEntry(BibEntry entry, BibDatabaseMode mode, Boolean isReformatFile) throws SaveException; - private void writeEpilogue(Writer writer, BibDatabase database) throws IOException { - if ((database.getEpilog() != null) && !(database.getEpilog().isEmpty())) { - writer.write(Globals.NEWLINE); - writer.write(database.getEpilog()); - writer.write(Globals.NEWLINE); - } - } + protected abstract void writeEpilogue(String epilogue) throws SaveException; /** * Writes all data to the specified writer, using each object's toString() method. */ - private void writeMetaData(Writer out, MetaData metaData) throws IOException { - if (metaData == null) { - return; - } + protected void writeMetaData(MetaData metaData) throws SaveException { + Objects.requireNonNull(metaData); Map serializedMetaData = metaData.getAsStringMap(); for(Map.Entry metaItem : serializedMetaData.entrySet()) { - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(Globals.NEWLINE); - stringBuilder.append(COMMENT_PREFIX + "{").append(MetaData.META_FLAG).append(metaItem.getKey()).append(":"); - stringBuilder.append(metaItem.getValue()); - stringBuilder.append("}"); - stringBuilder.append(Globals.NEWLINE); - - out.write(stringBuilder.toString()); - } - } - - private void writePreamble(Writer fw, String preamble) throws IOException { - if (preamble != null) { - fw.write(Globals.NEWLINE); - fw.write(PREAMBLE_PREFIX + "{"); - fw.write(preamble); - fw.write('}' + Globals.NEWLINE); + writeMetaDataItem(metaItem); } } - private void writeString(Writer fw, BibtexString bs, Map remaining, int maxKeyLength, - Boolean reformatFile) - throws IOException { - // First remove this from the "remaining" list so it can't cause problem with circular refs: - remaining.remove(bs.getName()); - - //if the string has not been modified, write it back as it was - if (!reformatFile && !bs.hasChanged()) { - fw.write(bs.getParsedSerialization()); - return; - } - - writeUserCommentsForString(bs, fw); - - if(isFirstStringInType) { - fw.write(Globals.NEWLINE); - } + protected abstract void writeMetaDataItem(Map.Entry metaItem) throws SaveException; - // Then we go through the string looking for references to other strings. If we find references - // to strings that we will write, but still haven't, we write those before proceeding. This ensures - // that the string order will be acceptable for BibTeX. - String content = bs.getContent(); - Matcher m; - while ((m = BibDatabaseWriter.REFERENCE_PATTERN.matcher(content)).find()) { - String foundLabel = m.group(1); - int restIndex = content.indexOf(foundLabel) + foundLabel.length(); - content = content.substring(restIndex); - Object referred = remaining.get(foundLabel.substring(1, foundLabel.length() - 1)); - // If the label we found exists as a key in the "remaining" Map, we go on and write it now: - if (referred != null) { - writeString(fw, (BibtexString) referred, remaining, maxKeyLength, reformatFile); - } - } - - fw.write(STRING_PREFIX + "{" + bs.getName() + StringUtil.repeatSpaces(maxKeyLength - bs.getName().length()) + " = "); - if (bs.getContent().isEmpty()) { - fw.write("{}"); - } else { - try { - String formatted = new LatexFieldFormatter().format(bs.getContent(), LatexFieldFormatter.BIBTEX_STRING); - fw.write(formatted); - } catch (IllegalArgumentException ex) { - throw new IllegalArgumentException( - "The # character is not allowed in BibTeX strings unless escaped as in '\\#'.\n" - + "Before saving, please edit any strings containing the # character."); - } - } - - fw.write("}" + Globals.NEWLINE); - } - - private void writeUserCommentsForString(BibtexString string, Writer out) throws IOException { - String userComments = string.getUserComments(); - - if(!userComments.isEmpty()) { - out.write(userComments + Globals.NEWLINE); - } - } + protected abstract void writePreamble(String preamble) throws SaveException; /** * Write all strings in alphabetical order, modified to produce a safe (for * BibTeX) order of the strings if they reference each other. * - * @param fw The Writer to send the output to. * @param database The database whose strings we should write. - * @param reformatFile - * @throws IOException If anything goes wrong in writing. */ - private void writeStrings(Writer fw, BibDatabase database, Boolean reformatFile) throws IOException { + private void writeStrings(BibDatabase database, Boolean reformatFile) throws SaveException { List strings = database.getStringKeySet().stream().map(database::getString).collect( Collectors.toList()); strings.sort(new BibtexStringComparator(true)); @@ -386,27 +261,57 @@ private void writeStrings(Writer fw, BibDatabase database, Boolean reformatFile) } for (BibtexString.Type t : BibtexString.Type.values()) { - isFirstStringInType = true; + boolean isFirstStringInType = true; for (BibtexString bs : strings) { if (remaining.containsKey(bs.getName()) && (bs.getType() == t)) { - writeString(fw, bs, remaining, maxKeyLength, reformatFile); + writeString(bs, isFirstStringInType, remaining, maxKeyLength, reformatFile); isFirstStringInType = false; } } } } - private void writeTypeDefinitions(Writer writer, Map types) throws IOException { + protected void writeString(BibtexString bibtexString, boolean isFirstString, Map remaining, int maxKeyLength, + Boolean reformatFile) + throws SaveException { + // First remove this from the "remaining" list so it can't cause problem with circular refs: + remaining.remove(bibtexString.getName()); + + // Then we go through the string looking for references to other strings. If we find references + // to strings that we will write, but still haven't, we write those before proceeding. This ensures + // that the string order will be acceptable for BibTeX. + String content = bibtexString.getContent(); + Matcher m; + while ((m = REFERENCE_PATTERN.matcher(content)).find()) { + String foundLabel = m.group(1); + int restIndex = content.indexOf(foundLabel) + foundLabel.length(); + content = content.substring(restIndex); + String label = foundLabel.substring(1, foundLabel.length() - 1); + + // If the label we found exists as a key in the "remaining" Map, we go on and write it now: + if (remaining.containsKey(label)) { + BibtexString referred = remaining.get(label); + writeString(referred, isFirstString, remaining, maxKeyLength, reformatFile); + } + } + + writeString(bibtexString, isFirstString, maxKeyLength, reformatFile); + } + + protected abstract void writeString(BibtexString bibtexString, boolean isFirstString, int maxKeyLength, Boolean reformatFile) + throws SaveException; + + protected void writeEntryTypeDefinitions(Map types) throws SaveException { for (EntryType type : types.values()) { if (type instanceof CustomEntryType) { - CustomEntryType customType = (CustomEntryType) type; - writer.write(Globals.NEWLINE); - writer.write(COMMENT_PREFIX + "{"); - writer.write(customType.getAsString()); - writer.write("}"); - writer.write(Globals.NEWLINE); + writeEntryTypeDefinition((CustomEntryType) type); } } } + protected abstract void writeEntryTypeDefinition(CustomEntryType customType) throws SaveException; + + protected SaveSession getActiveSession() { + return session; + } } diff --git a/src/main/java/net/sf/jabref/exporter/BibtexDatabaseWriter.java b/src/main/java/net/sf/jabref/exporter/BibtexDatabaseWriter.java new file mode 100644 index 000000000000..abd599c977a7 --- /dev/null +++ b/src/main/java/net/sf/jabref/exporter/BibtexDatabaseWriter.java @@ -0,0 +1,168 @@ +/* Copyright (C) 2003-2016 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.exporter; + +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Map; + +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.Globals; +import net.sf.jabref.MetaData; +import net.sf.jabref.logic.bibtex.BibEntryWriter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.BibtexString; +import net.sf.jabref.model.entry.CustomEntryType; + +public class BibtexDatabaseWriter extends BibDatabaseWriter { + + private static final String STRING_PREFIX = "@String"; + private static final String COMMENT_PREFIX = "@Comment"; + private static final String PREAMBLE_PREFIX = "@Preamble"; + + public BibtexDatabaseWriter(SaveSessionFactory saveSessionFactory) { + super(saveSessionFactory); + } + + @Override + protected void writeEpilogue(String epilogue) throws SaveException { + if (!StringUtil.isNullOrEmpty(epilogue)) { + try { + getWriter().write(Globals.NEWLINE); + getWriter().write(epilogue); + getWriter().write(Globals.NEWLINE); + } catch (IOException e) { + throw new SaveException(e); + } + } + } + + @Override + protected void writeMetaDataItem(Map.Entry metaItem) throws SaveException { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(Globals.NEWLINE); + stringBuilder.append(COMMENT_PREFIX + "{").append(MetaData.META_FLAG).append(metaItem.getKey()).append(":"); + stringBuilder.append(metaItem.getValue()); + stringBuilder.append("}"); + stringBuilder.append(Globals.NEWLINE); + + try { + getWriter().write(stringBuilder.toString()); + } catch (IOException e) { + throw new SaveException(e); + } + } + + @Override + protected void writePreamble(String preamble) throws SaveException { + if (!StringUtil.isNullOrEmpty(preamble)) { + try { + getWriter().write(Globals.NEWLINE); + getWriter().write(PREAMBLE_PREFIX + "{"); + getWriter().write(preamble); + getWriter().write('}' + Globals.NEWLINE); + } catch (IOException e) { + throw new SaveException(e); + } + } + } + + @Override + protected void writeString(BibtexString bibtexString, boolean isFirstString, int maxKeyLength, Boolean reformatFile) throws SaveException { + try { + // If the string has not been modified, write it back as it was + if (!reformatFile && !bibtexString.hasChanged()) { + getWriter().write(bibtexString.getParsedSerialization()); + return; + } + + // Write user comments + String userComments = bibtexString.getUserComments(); + if(!userComments.isEmpty()) { + getWriter().write(userComments + Globals.NEWLINE); + } + + if (isFirstString) { + getWriter().write(Globals.NEWLINE); + } + + getWriter().write(STRING_PREFIX + "{" + bibtexString.getName() + StringUtil + .repeatSpaces(maxKeyLength - bibtexString.getName().length()) + " = "); + if (bibtexString.getContent().isEmpty()) { + getWriter().write("{}"); + } else { + try { + String formatted = new LatexFieldFormatter().format(bibtexString.getContent(), LatexFieldFormatter.BIBTEX_STRING); + getWriter().write(formatted); + } catch (IllegalArgumentException ex) { + throw new IllegalArgumentException( + "The # character is not allowed in BibTeX strings unless escaped as in '\\#'.\n" + "Before saving, please edit any strings containing the # character."); + } + } + + getWriter().write("}" + Globals.NEWLINE); + } catch (IOException e) { + throw new SaveException(e); + } + } + + @Override + protected void writeEntryTypeDefinition(CustomEntryType customType) throws SaveException { + try { + getWriter().write(Globals.NEWLINE); + getWriter().write(COMMENT_PREFIX + "{"); + getWriter().write(customType.getAsString()); + getWriter().write("}"); + getWriter().write(Globals.NEWLINE); + } catch (IOException e) { + throw new SaveException(e); + } + } + + @Override + protected void writePrelogue(BibDatabaseContext bibDatabaseContext, Charset encoding) throws SaveException { + if(encoding == null) { + return; + } + + // Writes the file encoding information. + try { + getWriter().write("% "); + getWriter().write(Globals.ENCODING_PREFIX + encoding); + getWriter().write(Globals.NEWLINE); + } catch (IOException e) { + throw new SaveException(e); + } + } + + @Override + protected void writeEntry(BibEntry entry, BibDatabaseMode mode, Boolean isReformatFile) throws SaveException { + BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new LatexFieldFormatter(), true); + try { + bibtexEntryWriter.write(entry, getWriter(), mode, isReformatFile); + } catch (IOException e) { + throw new SaveException(e, entry); + } + } + + private Writer getWriter() { + return getActiveSession().getWriter(); + } +} diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormat.java b/src/main/java/net/sf/jabref/exporter/ExportFormat.java index b4d12d013e57..97475878f7e8 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/ExportFormat.java @@ -24,6 +24,7 @@ import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -186,19 +187,19 @@ public void performExport(final BibDatabaseContext databaseContext, final String if (entries.isEmpty()) { // Do not export if no entries to export -- avoids exports with only template text return; } - File outFile = new File(file); + Path outFile = Paths.get(file); SaveSession ss = null; if (this.encoding != null) { try { - ss = new SaveSession(this.encoding, false); - } catch (IOException ex) { + ss = new FileSaveSession(this.encoding, false); + } catch (SaveException ex) { // Perhaps the overriding encoding doesn't work? // We will fall back on the default encoding. LOGGER.warn("Can not get save session.", ex); } } if (ss == null) { - ss = new SaveSession(encoding, false); + ss = new FileSaveSession(encoding, false); } try (VerifyingWriter ps = ss.getWriter()) { @@ -369,7 +370,7 @@ public FileFilter getFileFilter() { return fileFilter; } - public void finalizeSaveSession(final SaveSession ss, File file) throws SaveException, IOException { + public void finalizeSaveSession(final SaveSession ss, Path file) throws SaveException, IOException { ss.getWriter().flush(); ss.getWriter().close(); diff --git a/src/main/java/net/sf/jabref/exporter/FileSaveSession.java b/src/main/java/net/sf/jabref/exporter/FileSaveSession.java new file mode 100644 index 000000000000..9530b6fbe043 --- /dev/null +++ b/src/main/java/net/sf/jabref/exporter/FileSaveSession.java @@ -0,0 +1,142 @@ +/* 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.exporter; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.io.FileBasedLock; +import net.sf.jabref.logic.util.io.FileUtil; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Class used to handle safe storage to disk. + *

    + * Usage: create a SaveSession giving the file to save to, the encoding, and whether to make a backup. The SaveSession + * will provide a Writer to store to, which actually goes to a temporary file. The Writer keeps track of whether all + * characters could be saved, and if not, which characters were not encodable. + *

    + * After saving is finished, the client should close the Writer. If the save should be put into effect, call commit(), + * otherwise call cancel(). When canceling, the temporary file is simply deleted and the target file remains unchanged. + * When committing, the temporary file is copied to the target file after making a backup if requested and if the target + * file already existed, and finally the temporary file is deleted. + *

    + * If committing fails, the temporary file will not be deleted. + */ +public class FileSaveSession extends SaveSession { + + private static final Log LOGGER = LogFactory.getLog(FileSaveSession.class); + + // Filenames. + private static final String BACKUP_EXTENSION = ".bak"; + private static final String TEMP_PREFIX = "jabref"; + private static final String TEMP_SUFFIX = "save.bib"; + private final boolean useLockFile; + private Path temporaryFile; + + public FileSaveSession(Charset encoding, boolean backup) throws SaveException { + this(encoding, backup, createTemporaryFile()); + } + + public FileSaveSession(Charset encoding, boolean backup, Path temporaryFile) throws SaveException { + super(encoding, backup, getWriterForFile(encoding, temporaryFile)); + this.temporaryFile = temporaryFile; + this.useLockFile = Globals.prefs.getBoolean(JabRefPreferences.USE_LOCK_FILES); + } + + private static VerifyingWriter getWriterForFile(Charset encoding, Path file) throws SaveException { + try { + return new VerifyingWriter(new FileOutputStream(file.toFile()), encoding); + } catch (FileNotFoundException e) { + throw new SaveException(e); + } + } + + private static Path createTemporaryFile() throws SaveException { + try { + return Files.createTempFile(FileSaveSession.TEMP_PREFIX, FileSaveSession.TEMP_SUFFIX); + } catch (IOException e) { + throw new SaveException(e); + } + } + + @Override + public void commit(Path file) throws SaveException { + if (file == null) { + return; + } + if (backup && Files.exists(file)) { + Path fileName = file.getFileName(); + Path backupFile = file.resolveSibling(fileName + BACKUP_EXTENSION); + try { + FileUtil.copyFile(file.toFile(), backupFile.toFile(), true); + } catch (IOException ex) { + LOGGER.error("Problem copying file", ex); + throw SaveException.BACKUP_CREATION; + } + } + try { + if (useLockFile) { + try { + if (FileBasedLock.createLockFile(file)) { + // Oops, the lock file already existed. Try to wait it out: + if (!FileBasedLock.waitForFileLock(file, 10)) { + throw SaveException.FILE_LOCKED; + } + } + } catch (IOException ex) { + LOGGER.error("Error when creating lock file.", ex); + } + } + + FileUtil.copyFile(temporaryFile.toFile(), file.toFile(), true); + } catch (IOException ex2) { + // If something happens here, what can we do to correct the problem? The file is corrupted, but we still + // have a clean copy in tmp. However, we just failed to copy tmp to file, so it's not likely that + // repeating the action will have a different result. + // On the other hand, our temporary file should still be clean, and won't be deleted. + throw new SaveException("Save failed while committing changes: " + ex2.getMessage(), + Localization.lang("Save failed while committing changes: %0", ex2.getMessage())); + } finally { + if (useLockFile) { + FileBasedLock.deleteLockFile(file); + } + } + try { + Files.delete(temporaryFile); + } catch (IOException e) { + LOGGER.warn("Cannot delete temporary file", e); + } + } + + @Override + public void cancel() { + try { + Files.delete(temporaryFile); + } catch (IOException e) { + LOGGER.warn("Cannot delete temporary file", e); + } + } +} diff --git a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java b/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java index 4f4c265f6a5b..f33852aec1be 100644 --- a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java @@ -15,10 +15,10 @@ */ package net.sf.jabref.exporter; -import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; import java.util.List; import java.util.Objects; @@ -45,7 +45,7 @@ public MSBibExportFormat() { @Override public void performExport(final BibDatabaseContext databaseContext, final String file, - final Charset encoding, List entries) throws IOException { + final Charset encoding, List entries) throws SaveException { Objects.requireNonNull(databaseContext); Objects.requireNonNull(entries); @@ -53,7 +53,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String return; } // forcing to use UTF8 output format for some problems with xml export in other encodings - SaveSession session = new SaveSession(StandardCharsets.UTF_8, false); + SaveSession session = new FileSaveSession(StandardCharsets.UTF_8, false); MSBibDatabase msBibDatabase = new MSBibDatabase(databaseContext.getDatabase(), entries); try (VerifyingWriter ps = session.getWriter()) { @@ -66,9 +66,9 @@ public void performExport(final BibDatabaseContext databaseContext, final String } catch (TransformerException | IllegalArgumentException | TransformerFactoryConfigurationError e) { throw new Error(e); } - finalizeSaveSession(session, new File(file)); - } catch (SaveException | IOException ex) { - throw new IOException(ex.getMessage()); + finalizeSaveSession(session, Paths.get(file)); + } catch (IOException ex) { + throw new SaveException(ex); } } } diff --git a/src/main/java/net/sf/jabref/exporter/ModsExportFormat.java b/src/main/java/net/sf/jabref/exporter/ModsExportFormat.java index c2b94a9ff192..b43f079a622a 100644 --- a/src/main/java/net/sf/jabref/exporter/ModsExportFormat.java +++ b/src/main/java/net/sf/jabref/exporter/ModsExportFormat.java @@ -15,10 +15,10 @@ */ package net.sf.jabref.exporter; -import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; import java.util.List; import java.util.Objects; @@ -45,14 +45,14 @@ public ModsExportFormat() { @Override public void performExport(final BibDatabaseContext databaseContext, final String file, - final Charset encoding, List entries) throws IOException { + final Charset encoding, List entries) throws SaveException { Objects.requireNonNull(databaseContext); Objects.requireNonNull(entries); if (entries.isEmpty()) { // Only export if entries exist return; } - SaveSession ss = new SaveSession(StandardCharsets.UTF_8, false); + SaveSession ss = new FileSaveSession(StandardCharsets.UTF_8, false); try (VerifyingWriter ps = ss.getWriter()) { MODSDatabase md = new MODSDatabase(databaseContext.getDatabase(), entries); @@ -65,9 +65,9 @@ public void performExport(final BibDatabaseContext databaseContext, final String } catch (TransformerException | IllegalArgumentException | TransformerFactoryConfigurationError e) { throw new Error(e); } - finalizeSaveSession(ss, new File(file)); - } catch (SaveException | IOException ex) { - throw new IOException(ex.getMessage()); + finalizeSaveSession(ss, Paths.get(file)); + } catch (IOException ex) { + throw new SaveException(ex); } } } diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java index d43042c583a7..f7245aebcd9c 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java @@ -120,7 +120,7 @@ public void run() { // lacking keys, before saving: panel.autoGenerateKeysBeforeSaving(); - if (FileBasedLock.waitForFileLock(panel.getBibDatabaseContext().getDatabaseFile(), 10)) { + if (FileBasedLock.waitForFileLock(panel.getBibDatabaseContext().getDatabaseFile().toPath(), 10)) { // Check for external modifications to alleviate multiuser concurrency issue when near // simultaneous saves occur to a shared database file: if true, do not perform the save // rather return instead. @@ -168,11 +168,10 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset encoding) frame.block(); try { SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs).withEncoding(encoding); - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); + BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter(FileSaveSession::new); if (selectedOnly) { - session = databaseWriter.savePartOfDatabase(panel.getBibDatabaseContext(), prefs, - panel.getSelectedEntries()); - + session = databaseWriter.savePartOfDatabase(panel.getBibDatabaseContext(), panel.getSelectedEntries(), + prefs); } else { session = databaseWriter.saveDatabase(panel.getBibDatabaseContext(), prefs); @@ -245,7 +244,7 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset encoding) try { if (commit) { - session.commit(file); + session.commit(file.toPath()); panel.getBibDatabaseContext().getMetaData().setEncoding(encoding); // Make sure to remember which encoding we used. } else { session.cancel(); @@ -257,7 +256,7 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset encoding) JOptionPane.YES_NO_OPTION); if (ans == JOptionPane.YES_OPTION) { session.setUseBackup(false); - session.commit(file); + session.commit(file.toPath()); panel.getBibDatabaseContext().getMetaData().setEncoding(encoding); } else { commit = false; @@ -384,7 +383,7 @@ private boolean checkExternalModification() { JabRefExecutorService.INSTANCE.execute(() -> { - if (!FileBasedLock.waitForFileLock(panel.getBibDatabaseContext().getDatabaseFile(), 10)) { + if (!FileBasedLock.waitForFileLock(panel.getBibDatabaseContext().getDatabaseFile().toPath(), 10)) { // TODO: GUI handling of the situation when the externally modified file keeps being locked. LOGGER.error("File locked, this will be trouble."); } diff --git a/src/main/java/net/sf/jabref/exporter/SaveException.java b/src/main/java/net/sf/jabref/exporter/SaveException.java index c8e83ebf825b..c2597d6c55d3 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveException.java +++ b/src/main/java/net/sf/jabref/exporter/SaveException.java @@ -62,6 +62,14 @@ public SaveException(String message, String localizedMessage, BibEntry entry) { this.entry = entry; } + public SaveException(Exception base) { + this(base.getMessage(), base.getLocalizedMessage()); + } + + public SaveException(Exception base, BibEntry entry) { + this(base.getMessage(), base.getLocalizedMessage(), entry); + } + public int getStatus() { return status; } diff --git a/src/main/java/net/sf/jabref/exporter/SavePreferences.java b/src/main/java/net/sf/jabref/exporter/SavePreferences.java index 4d8375522c8e..5230f1953b97 100644 --- a/src/main/java/net/sf/jabref/exporter/SavePreferences.java +++ b/src/main/java/net/sf/jabref/exporter/SavePreferences.java @@ -115,6 +115,10 @@ public SavePreferences withReformatFile(boolean reformatFile) { this.saveType, this.takeMetadataSaveOrderInAccount, reformatFile); } + public Charset getEncodingOrDefault() { + return encoding == null ? Charset.defaultCharset() : encoding; + } + public enum DatabaseSaveType { ALL, PLAIN_BIBTEX diff --git a/src/main/java/net/sf/jabref/exporter/SaveSession.java b/src/main/java/net/sf/jabref/exporter/SaveSession.java index 81a23852e6cf..57898db111dd 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveSession.java +++ b/src/main/java/net/sf/jabref/exporter/SaveSession.java @@ -1,87 +1,42 @@ -/* 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. +/* + * Copyright (C) 2003-2016 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. + */ - 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.exporter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Objects; -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.logic.util.io.FileBasedLock; -import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.FieldChange; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Class used to handle safe storage to disk. - *

    - * Usage: create a SaveSession giving the file to save to, the encoding, and whether to make a backup. The SaveSession - * will provide a Writer to store to, which actually goes to a temporary file. The Writer keeps track of whether all - * characters could be saved, and if not, which characters were not encodable. - *

    - * After saving is finished, the client should close the Writer. If the save should be put into effect, call commit(), - * otherwise call cancel(). When canceling, the temporary file is simply deleted and the target file remains unchanged. - * When committing, the temporary file is copied to the target file after making a backup if requested and if the target - * file already existed, and finally the temporary file is deleted. - *

    - * If committing fails, the temporary file will not be deleted. - */ -public class SaveSession { - - private static final Log LOGGER = LogFactory.getLog(SaveSession.class); - - // Filenames. - private static final String BACKUP_EXTENSION = ".bak"; - public static final String LOCKFILE_SUFFIX = ".lock"; - - // The age in ms of a lockfile before JabRef will offer to "steal" the locked file: - public static final long LOCKFILE_CRITICAL_AGE = 60000; - private static final String TEMP_PREFIX = "jabref"; - - private static final String TEMP_SUFFIX = "save.bib"; - private final File tmp; - private final Charset encoding; - private boolean backup; - private final boolean useLockFile; - - private final VerifyingWriter writer; +public abstract class SaveSession { + protected final Charset encoding; + protected final VerifyingWriter writer; private final List undoableFieldChanges = new ArrayList<>(); + protected boolean backup; - - public SaveSession(Charset encoding, boolean backup) throws IOException { - tmp = File.createTempFile(SaveSession.TEMP_PREFIX, SaveSession.TEMP_SUFFIX); - useLockFile = Globals.prefs.getBoolean(JabRefPreferences.USE_LOCK_FILES); + protected SaveSession(Charset encoding, boolean backup, VerifyingWriter writer) { + this.encoding = Objects.requireNonNull(encoding); this.backup = backup; - this.encoding = encoding; - /* Using - try (FileOutputStream fos = new FileOutputStream(tmp)) { - writer = new VerifyingWriter(fos, encoding); - } - doesn't work since fos is closed after assigning write, - leading to that fos may never be closed at all - */ - writer = new VerifyingWriter(new FileOutputStream(tmp), encoding); + this.writer = Objects.requireNonNull(writer); } public VerifyingWriter getWriter() { @@ -96,101 +51,13 @@ public void setUseBackup(boolean useBackup) { this.backup = useBackup; } - public void commit(File file) throws SaveException { - if (file == null) { - return; - } - if (file.exists() && backup) { - String name = file.getName(); - String path = file.getParent(); - File backupFile = new File(path, name + BACKUP_EXTENSION); - try { - FileUtil.copyFile(file, backupFile, true); - } catch (IOException ex) { - LOGGER.error("Problem copying file", ex); - throw SaveException.BACKUP_CREATION; - } - } - try { - if (useLockFile) { - try { - if (createLockFile(file)) { - // Oops, the lock file already existed. Try to wait it out: - if (!FileBasedLock.waitForFileLock(file, 10)) { - throw SaveException.FILE_LOCKED; - } - - } - } catch (IOException ex) { - LOGGER.error("Error when creating lock file.", ex); - } - } + public abstract void commit(Path file) throws SaveException; - FileUtil.copyFile(tmp, file, true); - } catch (IOException ex2) { - // If something happens here, what can we do to correct the problem? The file is corrupted, but we still - // have a clean copy in tmp. However, we just failed to copy tmp to file, so it's not likely that - // repeating the action will have a different result. - // On the other hand, our temporary file should still be clean, and won't be deleted. - throw new SaveException("Save failed while committing changes: " + ex2.getMessage(), - Localization.lang("Save failed while committing changes: %0", ex2.getMessage())); - } finally { - if (useLockFile) { - deleteLockFile(file); - } - } - if (!tmp.delete()) { - LOGGER.info("Cannot delete temporary file"); - } + public void commit(String path) throws SaveException { + commit(Paths.get(path)); } - public void cancel() { - if (!tmp.delete()) { - LOGGER.info("Cannot delete temporary file"); - } - } - - /** - * Check if a lock file exists, and create it if it doesn't. - * - * @return true if the lock file already existed - * @throws IOException if something happens during creation. - */ - private boolean createLockFile(File file) throws IOException { - File lock = new File(file.getPath() + SaveSession.LOCKFILE_SUFFIX); - if (lock.exists()) { - return true; - } - try (FileOutputStream out = new FileOutputStream(lock)) { - out.write(0); - out.close(); - } catch (IOException ex) { - LOGGER.error("Error when creating lock file.", ex); - } - lock.deleteOnExit(); - return false; - } - - /** - * Check if a lock file exists, and delete it if it does. - * - * @return true if the lock file existed, false otherwise. - * @throws IOException if something goes wrong. - */ - private boolean deleteLockFile(File file) { - File lock = new File(file.getPath() + SaveSession.LOCKFILE_SUFFIX); - if (!lock.exists()) { - return false; - } - if (!lock.delete()) { - LOGGER.info("Cannot delete lock file"); - } - return true; - } - - public File getTemporaryFile() { - return tmp; - } + public abstract void cancel(); public List getFieldChanges() { return undoableFieldChanges; diff --git a/src/main/java/net/sf/jabref/exporter/StringSaveSession.java b/src/main/java/net/sf/jabref/exporter/StringSaveSession.java new file mode 100644 index 000000000000..3fec5c30f30b --- /dev/null +++ b/src/main/java/net/sf/jabref/exporter/StringSaveSession.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003-2016 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.exporter; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class StringSaveSession extends SaveSession { + + private static final Log LOGGER = LogFactory.getLog(StringSaveSession.class); + + private final ByteArrayOutputStream outputStream; + + public StringSaveSession(Charset encoding, boolean backup) { + this(encoding, backup, new ByteArrayOutputStream()); + } + + private StringSaveSession(Charset encoding, boolean backup, ByteArrayOutputStream outputStream) { + super(encoding, backup, new VerifyingWriter(outputStream, encoding)); + this.outputStream = outputStream; + } + + public String getStringValue() { + try { + return outputStream.toString(encoding.name()); + } catch (UnsupportedEncodingException e) { + LOGGER.warn(e); + return ""; + } + } + + @Override + public void commit(Path file) throws SaveException { + try { + Files.write(file, outputStream.toByteArray()); + } catch (IOException e) { + throw new SaveException(e); + } + } + + @Override + public void cancel() { + try { + outputStream.close(); + } catch (IOException e) { + LOGGER.warn(e); + } + } +} diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 4b7acbbb5bbd..db900bd77cbb 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -63,8 +63,9 @@ import net.sf.jabref.collab.FileUpdatePanel; import net.sf.jabref.event.EntryAddedEvent; import net.sf.jabref.event.EntryChangedEvent; -import net.sf.jabref.exporter.BibDatabaseWriter; +import net.sf.jabref.exporter.BibtexDatabaseWriter; import net.sf.jabref.exporter.ExportToClipboardAction; +import net.sf.jabref.exporter.FileSaveSession; import net.sf.jabref.exporter.SaveDatabaseAction; import net.sf.jabref.exporter.SaveException; import net.sf.jabref.exporter.SavePreferences; @@ -1104,9 +1105,9 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset enc, try { SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs).withEncoding(enc) .withSaveType(saveType); - BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); + BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter(FileSaveSession::new); if (selectedOnly) { - session = databaseWriter.savePartOfDatabase(bibDatabaseContext, prefs, mainTable.getSelectedEntries()); + session = databaseWriter.savePartOfDatabase(bibDatabaseContext, mainTable.getSelectedEntries(), prefs); } else { session = databaseWriter.saveDatabase(bibDatabaseContext, prefs); } @@ -1173,7 +1174,7 @@ private boolean saveDatabase(File file, boolean selectedOnly, Charset enc, } if (commit) { - session.commit(file); + session.commit(file.toPath()); this.bibDatabaseContext.getMetaData().setEncoding(enc); // Make sure to remember which encoding we used. } else { session.cancel(); @@ -2170,7 +2171,7 @@ public void fileUpdated() { // Test: running scan automatically in background if ((getBibDatabaseContext().getDatabaseFile() != null) - && !FileBasedLock.waitForFileLock(getBibDatabaseContext().getDatabaseFile(), 10)) { + && !FileBasedLock.waitForFileLock(getBibDatabaseContext().getDatabaseFile().toPath(), 10)) { // The file is locked even after the maximum wait. Do nothing. LOGGER.error("File updated externally, but change scan failed because the file is locked."); // Perturb the stored timestamp so successive checks are made: diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index d894601bb114..4777284a30e1 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -19,10 +19,12 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Optional; import javax.swing.Action; import javax.swing.JOptionPane; @@ -35,7 +37,6 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.exporter.AutoSaveManager; -import net.sf.jabref.exporter.SaveSession; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.IconTheme; @@ -217,10 +218,11 @@ private void openTheFile(File file, boolean raisePanel) { Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, file.getPath()); // Should this be done _after_ we know it was successfully opened? - if (FileBasedLock.hasLockFile(file)) { - long modificationTIme = FileBasedLock.getLockFileTimeStamp(file); - if ((modificationTIme != -1) - && ((System.currentTimeMillis() - modificationTIme) > SaveSession.LOCKFILE_CRITICAL_AGE)) { + if (FileBasedLock.hasLockFile(file.toPath())) { + Optional modificationTime = FileBasedLock.getLockFileTimeStamp(file.toPath()); + if ((modificationTime.isPresent()) && ( + (System.currentTimeMillis() - modificationTime.get().toMillis()) + > FileBasedLock.LOCKFILE_CRITICAL_AGE)) { // The lock file is fairly old, so we can offer to "steal" the file: int answer = JOptionPane.showConfirmDialog(null, "" + Localization.lang("Error opening file") + " '" + fileName + "'. " @@ -228,11 +230,11 @@ private void openTheFile(File file, boolean raisePanel) { + Localization.lang("Do you want to override the file lock?"), Localization.lang("File locked"), JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.YES_OPTION) { - FileBasedLock.deleteLockFile(file); + FileBasedLock.deleteLockFile(file.toPath()); } else { return; } - } else if (!FileBasedLock.waitForFileLock(file, 10)) { + } else if (!FileBasedLock.waitForFileLock(file.toPath(), 10)) { JOptionPane.showMessageDialog(null, Localization.lang("Error opening file") + " '" + fileName + "'. " + Localization.lang("File is locked by another JabRef instance."), @@ -383,7 +385,7 @@ public static ParserResult loadDatabaseOrAutoSave(String name, boolean ignoreAut } } - if (!FileBasedLock.waitForFileLock(file, 10)) { + if (!FileBasedLock.waitForFileLock(file.toPath(), 10)) { LOGGER.error(Localization.lang("Error opening file") + " '" + name + "'. " + "File is locked by another JabRef instance."); return ParserResult.getNullResult(); diff --git a/src/main/java/net/sf/jabref/logic/util/io/FileBasedLock.java b/src/main/java/net/sf/jabref/logic/util/io/FileBasedLock.java index ae6d5c45f84c..2fff8d7e83dc 100644 --- a/src/main/java/net/sf/jabref/logic/util/io/FileBasedLock.java +++ b/src/main/java/net/sf/jabref/logic/util/io/FileBasedLock.java @@ -1,14 +1,22 @@ package net.sf.jabref.logic.util.io; -import java.io.File; - -import net.sf.jabref.exporter.SaveSession; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.util.Optional; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class FileBasedLock { + /** + * The age in ms of a lockfile before JabRef will offer to "steal" the locked file. + */ + public static final long LOCKFILE_CRITICAL_AGE = 60000; + private static final String LOCKFILE_SUFFIX = ".lock"; private static final Log LOGGER = LogFactory.getLog(FileBasedLock.class); @@ -21,7 +29,7 @@ public class FileBasedLock { * @param maxWaitCount The maximum number of times to wait. * @return true if the lock file is gone, false if it is still there. */ - public static boolean waitForFileLock(File file, int maxWaitCount) { + public static boolean waitForFileLock(Path file, int maxWaitCount) { // Check if the file is locked by another JabRef user: int lockCheckCount = 0; while (hasLockFile(file)) { @@ -43,33 +51,67 @@ public static boolean waitForFileLock(File file, int maxWaitCount) { * @param file The file to check. * @return true if a lock file exists, false otherwise. */ - public static boolean hasLockFile(File file) { - File lock = new File(file.getPath() + SaveSession.LOCKFILE_SUFFIX); - return lock.exists(); + public static boolean hasLockFile(Path file) { + Path lockFile = getLockFilePath(file); + return Files.exists(lockFile); } /** * Find the lock file's last modified time, if it has a lock file. * @param file The file to check. - * @return the last modified time if lock file exists, -1 otherwise. + * @return the last modified time if lock file exists, empty optional otherwise. */ - public static long getLockFileTimeStamp(File file) { - File lock = new File(file.getPath() + SaveSession.LOCKFILE_SUFFIX); - return lock.exists() ? lock.lastModified() : -1; + public static Optional getLockFileTimeStamp(Path file) { + Path lockFile = getLockFilePath(file); + try { + return Files.exists(lockFile) ? + Optional.of(Files.readAttributes(lockFile, BasicFileAttributes.class).lastModifiedTime()) : + Optional.empty(); + } catch (IOException e) { + return Optional.empty(); + } } /** * Check if a lock file exists, and delete it if it does. + * * @return true if the lock file existed, false otherwise. */ - public static boolean deleteLockFile(File file) { - File lock = new File(file.getPath() + SaveSession.LOCKFILE_SUFFIX); - if (!lock.exists()) { + public static boolean deleteLockFile(Path file) { + Path lockFile = getLockFilePath(file); + if (!Files.exists(lockFile)) { return false; } - if (!lock.delete()) { - LOGGER.warn("Cannot delete lock file"); + try { + Files.delete(lockFile); + } catch (IOException e) { + LOGGER.warn("Cannot delete lock file", e); } return true; } + + /** + * Check if a lock file exists, and create it if it doesn't. + * + * @return true if the lock file already existed + * @throws IOException if something happens during creation. + */ + public static boolean createLockFile(Path file) throws IOException { + Path lockFile = getLockFilePath(file); + if (Files.exists(lockFile)) { + return true; + } + + try { + Files.write(lockFile, "0".getBytes()); + } catch (IOException ex) { + LOGGER.error("Error when creating lock file.", ex); + } + lockFile.toFile().deleteOnExit(); + return false; + } + + private static Path getLockFilePath(Path file) { + return file.resolveSibling(file.getFileName() + LOCKFILE_SUFFIX); + } } diff --git a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java index 5e08b24b10ac..432d98bd26d0 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java @@ -653,4 +653,7 @@ public static String repeat(int n, char c) { } + public static boolean isNullOrEmpty(String toTest) { + return (toTest == null || toTest.isEmpty()); + } } diff --git a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java b/src/test/java/net/sf/jabref/exporter/BibtexDatabaseWriterTest.java similarity index 68% rename from src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java rename to src/test/java/net/sf/jabref/exporter/BibtexDatabaseWriterTest.java index 57fef45bc270..e9cd0d576629 100644 --- a/src/test/java/net/sf/jabref/exporter/BibDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/exporter/BibtexDatabaseWriterTest.java @@ -1,8 +1,6 @@ package net.sf.jabref.exporter; import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Path; @@ -19,7 +17,6 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.importer.fileformat.ImportFormat; -import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.logic.formatter.casechanger.LowerCaseFormatter; @@ -40,186 +37,175 @@ import com.google.common.base.Charsets; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -public class BibDatabaseWriterTest { +public class BibtexDatabaseWriterTest { - private BibDatabaseWriter databaseWriter; - private StringWriter stringWriter; + private BibtexDatabaseWriter databaseWriter; private BibDatabase database; private MetaData metaData; private BibDatabaseContext bibtexContext; - @BeforeClass - public static void setUpClass() { + @Before + public void setUp() throws SaveException, IOException { Globals.prefs = JabRefPreferences.getInstance(); - } - @Before - public void setUp() { - databaseWriter = new BibDatabaseWriter(); - stringWriter = new StringWriter(); + // Write to a string instead of to a file + databaseWriter = new BibtexDatabaseWriter<>(StringSaveSession::new); + database = new BibDatabase(); metaData = new MetaData(); bibtexContext = new BibDatabaseContext(database, metaData, new Defaults(BibDatabaseMode.BIBTEX)); } @Test(expected = NullPointerException.class) - public void writeWithNullWriterThrowsException() throws IOException { - databaseWriter.writePartOfDatabase(null, bibtexContext, Collections.emptyList(), mock(SavePreferences.class)); - } - - @Test(expected = NullPointerException.class) - public void writeWithNullContextThrowsException() throws IOException { - databaseWriter.writePartOfDatabase(mock(Writer.class), null, Collections.emptyList(), new SavePreferences()); + public void writeWithNullContextThrowsException() throws Exception { + databaseWriter.savePartOfDatabase(null, Collections.emptyList(), new SavePreferences()); } @Test(expected = NullPointerException.class) - public void writeWithNullEntriesThrowsException() throws IOException { - databaseWriter.writePartOfDatabase(mock(Writer.class), bibtexContext, null, new SavePreferences()); + public void writeWithNullEntriesThrowsException() throws Exception { + databaseWriter.savePartOfDatabase(bibtexContext, null, new SavePreferences()); } @Test(expected = NullPointerException.class) - public void writeWithNullPreferencesThrowsException() throws IOException { - databaseWriter.writePartOfDatabase(mock(Writer.class), bibtexContext, Collections.emptyList(), null); + public void writeWithNullPreferencesThrowsException() throws Exception { + databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), null); } @Test - public void writeEncoding() throws IOException { + public void writeEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); - assertEquals("% Encoding: US-ASCII" + Globals.NEWLINE, stringWriter.toString()); + assertEquals("% Encoding: US-ASCII" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writePreamble() throws IOException { + public void writePreamble() throws Exception { database.setPreamble("Test preamble"); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); - assertEquals(Globals.NEWLINE + "@Preamble{Test preamble}" + Globals.NEWLINE, stringWriter.toString()); + assertEquals(Globals.NEWLINE + "@Preamble{Test preamble}" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writePreambleAndEncoding() throws IOException { + public void writePreambleAndEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); database.setPreamble("Test preamble"); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); assertEquals("% Encoding: US-ASCII" + Globals.NEWLINE + Globals.NEWLINE + - "@Preamble{Test preamble}" + Globals.NEWLINE, stringWriter.toString()); + "@Preamble{Test preamble}" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeEntry() throws IOException { + public void writeEntry() throws Exception { BibEntry entry = new BibEntry(); entry.setType(BibtexEntryTypes.ARTICLE); database.insertEntry(entry); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.singletonList(entry), - new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Article{," + Globals.NEWLINE + "}" + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-meta: databaseType:bibtex;}" - + Globals.NEWLINE, stringWriter.toString()); + + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeEncodingAndEntry() throws IOException { + public void writeEncodingAndEntry() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); BibEntry entry = new BibEntry(); entry.setType(BibtexEntryTypes.ARTICLE); database.insertEntry(entry); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.singletonList(entry), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry), preferences); assertEquals("% Encoding: US-ASCII" + Globals.NEWLINE + Globals.NEWLINE + "@Article{," + Globals.NEWLINE + "}" + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-meta: databaseType:bibtex;}" - + Globals.NEWLINE, stringWriter.toString()); + + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeEpilogue() throws IOException { + public void writeEpilogue() throws Exception { database.setEpilog("Test epilog"); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); - assertEquals(Globals.NEWLINE + "Test epilog" + Globals.NEWLINE, stringWriter.toString()); + assertEquals(Globals.NEWLINE + "Test epilog" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeEpilogueAndEncoding() throws IOException { + public void writeEpilogueAndEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); database.setEpilog("Test epilog"); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); assertEquals("% Encoding: US-ASCII" + Globals.NEWLINE + Globals.NEWLINE + - "Test epilog" + Globals.NEWLINE, stringWriter.toString()); + "Test epilog" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeMetadata() throws IOException { + public void writeMetadata() throws Exception { DatabaseLabelPattern labelPattern = new DatabaseLabelPattern(); labelPattern.setDefaultValue("test"); metaData.setLabelPattern(labelPattern); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: keypatterndefault:test;}" + Globals.NEWLINE, - stringWriter.toString()); + session.getStringValue()); } @Test - public void writeMetadataAndEncoding() throws IOException { + public void writeMetadataAndEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); DatabaseLabelPattern labelPattern = new DatabaseLabelPattern(); labelPattern.setDefaultValue("test"); metaData.setLabelPattern(labelPattern); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); assertEquals("% Encoding: US-ASCII" + Globals.NEWLINE + Globals.NEWLINE + - "@Comment{jabref-meta: keypatterndefault:test;}" + Globals.NEWLINE, stringWriter.toString()); + "@Comment{jabref-meta: keypatterndefault:test;}" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeGroups() throws IOException, ParseException { + public void writeGroups() throws Exception { GroupTreeNode groupRoot = GroupTreeNode.fromGroup(new AllEntriesGroup()); groupRoot.addSubgroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING)); metaData.setGroups(groupRoot); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); // @formatter:off assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: groupstree:" + Globals.NEWLINE + "0 AllEntriesGroup:;" + Globals.NEWLINE + "1 ExplicitGroup:test\\;2\\;;" + Globals.NEWLINE - + "}" + Globals.NEWLINE, stringWriter.toString()); + + "}" + Globals.NEWLINE, session.getStringValue()); // @formatter:on } @Test - public void writeGroupsAndEncoding() throws IOException, ParseException { + public void writeGroupsAndEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); GroupTreeNode groupRoot = GroupTreeNode.fromGroup(new AllEntriesGroup()); groupRoot.addChild(GroupTreeNode.fromGroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING))); metaData.setGroups(groupRoot); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); // @formatter:off assertEquals( @@ -228,40 +214,39 @@ public void writeGroupsAndEncoding() throws IOException, ParseException { + "@Comment{jabref-meta: groupstree:" + Globals.NEWLINE + "0 AllEntriesGroup:;" + Globals.NEWLINE + "1 ExplicitGroup:test\\;2\\;;" + Globals.NEWLINE - + "}" + Globals.NEWLINE, stringWriter.toString()); + + "}" + Globals.NEWLINE, session.getStringValue()); // @formatter:on } @Test - public void writeString() throws IOException { + public void writeString() throws Exception { database.addString(new BibtexString("id", "name", "content")); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); - assertEquals(Globals.NEWLINE + "@String{name = {content}}" + Globals.NEWLINE, stringWriter.toString()); + assertEquals(Globals.NEWLINE + "@String{name = {content}}" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeStringAndEncoding() throws IOException { + public void writeStringAndEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); database.addString(new BibtexString("id", "name", "content")); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); assertEquals("% Encoding: US-ASCII" + Globals.NEWLINE + Globals.NEWLINE + - "@String{name = {content}}" + Globals.NEWLINE, stringWriter.toString()); + "@String{name = {content}}" + Globals.NEWLINE, session.getStringValue()); } @Test - public void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws IOException { + public void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws Exception { try { EntryTypes.addOrModifyCustomEntryType(new CustomEntryType("customizedType", "required", "optional")); BibEntry entry = new BibEntry(); entry.setType("customizedType"); database.insertEntry(entry); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.singletonList(entry), - new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry), new SavePreferences()); assertEquals( Globals.NEWLINE + @@ -269,14 +254,14 @@ public void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws IOExc + "@Comment{jabref-meta: databaseType:bibtex;}" + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-entrytype: Customizedtype: req[required] opt[optional]}" + Globals.NEWLINE, - stringWriter.toString()); + session.getStringValue()); } finally { EntryTypes.removeAllCustomEntryTypes(); } } @Test - public void roundtrip() throws IOException { + public void roundtrip() throws Exception { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); Charset encoding = StandardCharsets.UTF_8; ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); @@ -285,14 +270,14 @@ public void roundtrip() throws IOException { BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), new Defaults(BibDatabaseMode.BIBTEX)); - databaseWriter.writePartOfDatabase(stringWriter, context, result.getDatabase().getEntries(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(context, result.getDatabase().getEntries(), preferences); try (Scanner scanner = new Scanner(testBibtexFile,encoding.name())) { - assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + assertEquals(scanner.useDelimiter("\\A").next(), session.getStringValue()); } } @Test - public void roundtripWithUserComment() throws IOException { + public void roundtripWithUserComment() throws Exception { Path testBibtexFile = Paths.get("src/test/resources/testbib/bibWithUserComments.bib"); Charset encoding = StandardCharsets.UTF_8; ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); @@ -301,14 +286,14 @@ public void roundtripWithUserComment() throws IOException { BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), new Defaults(BibDatabaseMode.BIBTEX)); - databaseWriter.writePartOfDatabase(stringWriter, context, result.getDatabase().getEntries(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(context, result.getDatabase().getEntries(), preferences); try (Scanner scanner = new Scanner(testBibtexFile,encoding.name())) { - assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + assertEquals(scanner.useDelimiter("\\A").next(), session.getStringValue()); } } @Test - public void roundtripWithUserCommentAndEntryChange() throws IOException { + public void roundtripWithUserCommentAndEntryChange() throws Exception { Path testBibtexFile = Paths.get("src/test/resources/testbib/bibWithUserComments.bib"); Charset encoding = StandardCharsets.UTF_8; ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); @@ -320,39 +305,37 @@ public void roundtripWithUserCommentAndEntryChange() throws IOException { BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), new Defaults(BibDatabaseMode.BIBTEX)); - databaseWriter.writePartOfDatabase(stringWriter, context, result.getDatabase().getEntries(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(context, result.getDatabase().getEntries(), preferences); try (Scanner scanner = new Scanner(Paths.get("src/test/resources/testbib/bibWithUserCommentAndEntryChange.bib"),encoding.name())) { - assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + assertEquals(scanner.useDelimiter("\\A").next(), session.getStringValue()); } } @Test - public void roundtripWithUserCommentBeforeStringAndChange() throws IOException { + public void roundtripWithUserCommentBeforeStringAndChange() throws Exception { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); Charset encoding = StandardCharsets.UTF_8; ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, encoding)); - BibtexString string = result.getDatabase().getStringValues().iterator().next(); - if(string.getContent().isEmpty()) { - // do nothing - } else { - string.setContent("my first string"); + for (BibtexString string : result.getDatabase().getStringValues()) { + // Mark them as changed + string.setContent(string.getContent()); } SavePreferences preferences = new SavePreferences().withEncoding(encoding).withSaveInOriginalOrder(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), new Defaults(BibDatabaseMode.BIBTEX)); - databaseWriter.writePartOfDatabase(stringWriter, context, result.getDatabase().getEntries(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(context, result.getDatabase().getEntries(), preferences); try (Scanner scanner = new Scanner(testBibtexFile,encoding.name())) { - assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + assertEquals(scanner.useDelimiter("\\A").next(), session.getStringValue()); } } @Test - public void writeSavedSerializationOfEntryIfUnchanged() throws IOException { + public void writeSavedSerializationOfEntryIfUnchanged() throws Exception { BibEntry entry = new BibEntry(); entry.setType(BibtexEntryTypes.ARTICLE); entry.setField("author", "Mr. author"); @@ -360,15 +343,14 @@ public void writeSavedSerializationOfEntryIfUnchanged() throws IOException { entry.setChanged(false); database.insertEntry(entry); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.singletonList(entry), - new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry), new SavePreferences()); assertEquals("presaved serialization" + Globals.NEWLINE + "@Comment{jabref-meta: databaseType:bibtex;}" - + Globals.NEWLINE, stringWriter.toString()); + + Globals.NEWLINE, session.getStringValue()); } @Test - public void reformatEntryIfAskedToDoSo() throws IOException { + public void reformatEntryIfAskedToDoSo() throws Exception { BibEntry entry = new BibEntry(); entry.setType(BibtexEntryTypes.ARTICLE); entry.setField("author", "Mr. author"); @@ -377,37 +359,37 @@ public void reformatEntryIfAskedToDoSo() throws IOException { database.insertEntry(entry); SavePreferences preferences = new SavePreferences().withReformatFile(true); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.singletonList(entry), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry), preferences); assertEquals(Globals.NEWLINE + "@Article{," + Globals.NEWLINE + " author = {Mr. author}," + Globals.NEWLINE + "}" + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-meta: databaseType:bibtex;}" + Globals.NEWLINE, - stringWriter.toString()); + session.getStringValue()); } @Test - public void writeSavedSerializationOfStringIfUnchanged() throws IOException { + public void writeSavedSerializationOfStringIfUnchanged() throws Exception { BibtexString string = new BibtexString("id", "name", "content"); string.setParsedSerialization("serialization"); database.addString(string); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); - assertEquals("serialization", stringWriter.toString()); + assertEquals("serialization", session.getStringValue()); } @Test - public void reformatStringIfAskedToDoSo() throws IOException { + public void reformatStringIfAskedToDoSo() throws Exception { BibtexString string = new BibtexString("id", "name", "content"); string.setParsedSerialization("wrong serialization"); database.addString(string); SavePreferences preferences = new SavePreferences().withReformatFile(true); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); - assertEquals(Globals.NEWLINE + "@String{name = {content}}" + Globals.NEWLINE, stringWriter.toString()); + assertEquals(Globals.NEWLINE + "@String{name = {content}}" + Globals.NEWLINE, session.getStringValue()); } @@ -417,10 +399,10 @@ public void writeSaveActions() throws Exception { Collections.singletonList(new FieldFormatterCleanup("title", new LowerCaseFormatter()))); metaData.setSaveActions(saveActions); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: saveActions:enabled;" + Globals.NEWLINE - + "title[lower_case]" + Globals.NEWLINE + ";}" + Globals.NEWLINE, stringWriter.toString()); + + "title[lower_case]" + Globals.NEWLINE + ";}" + Globals.NEWLINE, session.getStringValue()); } @Test @@ -430,11 +412,11 @@ public void writeSaveOrderConfig() throws Exception { new SaveOrderConfig.SortCriterion("abstract", false)); metaData.setSaveOrderConfig(saveOrderConfig); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: saveOrderConfig:specified;author;false;year;true;abstract;false;}" - + Globals.NEWLINE, stringWriter.toString()); + + Globals.NEWLINE, session.getStringValue()); } @Test @@ -444,41 +426,41 @@ public void writeCustomKeyPattern() throws Exception { pattern.addLabelPattern("article", "articleTest"); metaData.setLabelPattern(pattern); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: keypattern_article:articleTest;}" + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-meta: keypatterndefault:test;}" + Globals.NEWLINE, - stringWriter.toString()); + session.getStringValue()); } @Test public void writeBiblatexMode() throws Exception { metaData.setMode(BibDatabaseMode.BIBLATEX); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: databaseType:biblatex;}" + Globals.NEWLINE, - stringWriter.toString()); + session.getStringValue()); } @Test public void writeProtectedFlag() throws Exception { metaData.markAsProtected(); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: protectedFlag:true;}" + Globals.NEWLINE, - stringWriter.toString()); + session.getStringValue()); } @Test public void writeContentSelectors() throws Exception { metaData.setContentSelectors("title", Arrays.asList("testWord", "word2")); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: selector_title:testWord;word2;}" + Globals.NEWLINE, - stringWriter.toString()); + session.getStringValue()); } @Test @@ -486,33 +468,33 @@ public void writeFileDirectories() throws Exception { metaData.setDefaultFileDirectory("\\Literature\\"); metaData.setUserFileDirectory("defaultOwner-user", "D:\\Documents"); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); assertEquals(Globals.NEWLINE + "@Comment{jabref-meta: fileDirectory:\\\\Literature\\\\;}" + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-meta: fileDirectory-defaultOwner-user:D:\\\\Documents;}" - + Globals.NEWLINE, stringWriter.toString()); + + Globals.NEWLINE, session.getStringValue()); } @Test public void writeNotEmptyContentSelectors() throws Exception { metaData.setContentSelectors("title", Collections.singletonList("")); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); - assertEquals("", stringWriter.toString()); + assertEquals("", session.getStringValue()); } @Test public void writeNotCompletelyEmptyContentSelectors() throws Exception { metaData.setContentSelectors("title", Collections.emptyList()); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, Collections.emptyList(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); - assertEquals("", stringWriter.toString()); + assertEquals("", session.getStringValue()); } @Test - public void writeEntriesSorted() throws IOException { + public void writeEntriesSorted() throws Exception { SaveOrderConfig saveOrderConfig = new SaveOrderConfig(false, new SaveOrderConfig.SortCriterion("author", false), new SaveOrderConfig.SortCriterion("year", true), new SaveOrderConfig.SortCriterion("abstract", false)); @@ -537,7 +519,7 @@ public void writeEntriesSorted() throws IOException { database.insertEntry(thirdEntry); database.insertEntry(firstEntry); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, database.getEntries(), new SavePreferences()); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, database.getEntries(), new SavePreferences()); assertEquals( Globals.NEWLINE + @@ -557,11 +539,11 @@ public void writeEntriesSorted() throws IOException { + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-meta: saveOrderConfig:specified;author;false;year;true;abstract;false;}" + Globals.NEWLINE - , stringWriter.toString()); + , session.getStringValue()); } @Test - public void writeEntriesInOriginalOrderWhenNoSaveOrderConfigIsSetInMetadata() throws IOException { + public void writeEntriesInOriginalOrderWhenNoSaveOrderConfigIsSetInMetadata() throws Exception { BibEntry firstEntry = new BibEntry(IdGenerator.next()); firstEntry.setType(BibtexEntryTypes.ARTICLE); firstEntry.setField("author", "A"); @@ -582,7 +564,7 @@ public void writeEntriesInOriginalOrderWhenNoSaveOrderConfigIsSetInMetadata() th database.insertEntry(thirdEntry); SavePreferences preferences = new SavePreferences().withSaveInOriginalOrder(false); - databaseWriter.writePartOfDatabase(stringWriter, bibtexContext, database.getEntries(), preferences); + StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, database.getEntries(), preferences); assertEquals( Globals.NEWLINE + @@ -601,7 +583,7 @@ public void writeEntriesInOriginalOrderWhenNoSaveOrderConfigIsSetInMetadata() th + Globals.NEWLINE + Globals.NEWLINE + "@Comment{jabref-meta: databaseType:bibtex;}" + Globals.NEWLINE - , stringWriter.toString()); + , session.getStringValue()); } } diff --git a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java index b9c1841fb7f7..c113d6190f35 100644 --- a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java +++ b/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java @@ -70,7 +70,7 @@ public void setUp() throws Exception { } @Test - public final void testPerformExport() throws IOException, URISyntaxException { + public final void testPerformExport() throws IOException, URISyntaxException, SaveException { String xmlFileName = filename.replace(".bib", ".xml"); Path importFile = Paths.get(MSBibExportFormatTestFiles.class.getResource(filename).toURI()); String tempFilename = tempFile.getCanonicalPath(); diff --git a/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java b/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java index 0b0d8b643d24..ffecbf00c36b 100644 --- a/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java +++ b/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java @@ -44,7 +44,7 @@ public void setUp() throws Exception { } @Test - public final void testPerformExportWithNoEntry() throws IOException { + public final void testPerformExportWithNoEntry() throws IOException, SaveException { List entries = Collections.emptyList(); String tempFileName = tempFile.getCanonicalPath(); msBibExportFormat.performExport(databaseContext, tempFileName, charset, entries); diff --git a/src/test/resources/testbib/complex.bib b/src/test/resources/testbib/complex.bib index ee64be35dc52..80e183118f92 100644 --- a/src/test/resources/testbib/complex.bib +++ b/src/test/resources/testbib/complex.bib @@ -5,6 +5,7 @@ @Preamble{preamble This is some arbitrary user comment that should be preserved @String{firstString = {my first string}} +This is some user comment in front of a string, should also be preserved. @String{secondString = {}} @ARTICLE{1102917, From e8cc78985c28bdaab9f5ec2d204c3e067d4f2bf4 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 16 Jul 2016 14:21:21 +0200 Subject: [PATCH 240/268] Refactored exporter and split it into gui and logic (#1574) * Refactored exporter and split it into gui and logic * Rebased * Some ErrorProne issues fixed * Removed unused imports * Redundant imports --- .../net/sf/jabref/benchmarks/Benchmarks.java | 6 +- src/main/java/net/sf/jabref/Globals.java | 2 +- src/main/java/net/sf/jabref/JabRefMain.java | 2 +- .../java/net/sf/jabref/JabRefPreferences.java | 6 +- src/main/java/net/sf/jabref/MetaData.java | 2 +- .../net/sf/jabref/cli/ArgumentProcessor.java | 16 +- .../java/net/sf/jabref/cli/JabRefCLI.java | 2 +- .../net/sf/jabref/collab/ChangeScanner.java | 12 +- .../net/sf/jabref/exporter/ExportFormats.java | 300 ------------------ .../java/net/sf/jabref/gui/BasePanel.java | 14 +- .../java/net/sf/jabref/gui/JabRefFrame.java | 14 +- .../java/net/sf/jabref/gui/PreviewPanel.java | 2 +- .../gui/cleanup/CleanupActionsListModel.java | 2 +- .../cleanup/FieldFormatterCleanupsPanel.java | 2 +- .../DatabasePropertiesDialog.java | 2 +- .../{ => gui}/exporter/AutoSaveManager.java | 8 +- .../exporter/CustomExportDialog.java | 2 +- .../sf/jabref/gui/exporter/ExportAction.java | 184 +++++++++++ .../exporter/ExportCustomizationDialog.java | 2 +- .../{ => gui}/exporter/ExportFileFilter.java | 10 +- .../exporter/ExportToClipboardAction.java | 4 +- .../{ => gui}/exporter/RtfSelection.java | 2 +- .../{ => gui}/exporter/SaveAllAction.java | 2 +- .../exporter/SaveDatabaseAction.java | 7 +- .../gui/preftabs/PreferencesDialog.java | 2 +- .../importer/AutosaveStartupPrompter.java | 2 +- .../jabref/importer/OpenDatabaseAction.java | 2 +- .../jabref/logic/cleanup/CleanupPreset.java | 2 +- .../exporter/BibDatabaseWriter.java | 3 +- .../exporter/BibtexDatabaseWriter.java | 2 +- .../exporter/CustomExportList.java | 2 +- .../exporter/ExportComparator.java | 2 +- .../{ => logic}/exporter/ExportFormat.java | 26 +- .../jabref/logic/exporter/ExportFormats.java | 130 ++++++++ .../exporter/FieldFormatterCleanups.java | 2 +- .../{ => logic}/exporter/FileSaveSession.java | 4 +- .../{ => logic}/exporter/IExportFormat.java | 9 +- .../exporter/MSBibExportFormat.java | 2 +- .../exporter/ModsExportFormat.java | 2 +- .../{ => logic}/exporter/OOCalcDatabase.java | 2 +- .../exporter/OpenDocumentRepresentation.java | 2 +- .../OpenDocumentSpreadsheetCreator.java | 2 +- .../exporter/OpenOfficeDocumentCreator.java | 2 +- .../{ => logic}/exporter/SaveException.java | 2 +- .../{ => logic}/exporter/SavePreferences.java | 2 +- .../{ => logic}/exporter/SaveSession.java | 2 +- .../exporter/StringSaveSession.java | 2 +- .../{ => logic}/exporter/VerifyingWriter.java | 2 +- .../sf/jabref/logic/groups/GroupTreeNode.java | 6 +- .../sf/jabref/logic/layout/format/Number.java | 2 +- .../jabref/sql/exporter/DatabaseExporter.java | 4 +- src/test/java/net/sf/jabref/MetaDataTest.java | 2 +- .../cleanup/CleanupActionsListModelTest.java | 2 +- .../importer/fileformat/BibtexParserTest.java | 2 +- .../logic/cleanup/CleanupWorkerTest.java | 2 +- .../exporter/BibtexDatabaseWriterTest.java | 5 +- .../exporter/ExportFormatTest.java | 2 +- .../exporter/FieldFormatterCleanupsTest.java | 2 +- .../exporter/HtmlExportFormatTest.java | 2 +- .../exporter/MSBibExportFormatTestFiles.java | 4 +- .../exporter/MsBibExportFormatTest.java | 2 +- .../logic/openoffice/CitationEntryTest.java | 1 - .../sf/jabref/model/entry/AuthorListTest.java | 4 +- .../exporter/MsBibExportFormatTest1.bib | 0 .../exporter/MsBibExportFormatTest1.xml | 0 .../exporter/MsBibExportFormatTest2.bib | 0 .../exporter/MsBibExportFormatTest2.xml | 0 .../exporter/MsBibExportFormatTest3.bib | 0 .../exporter/MsBibExportFormatTest3.xml | 0 .../exporter/MsBibExportFormatTest4.bib | 0 .../exporter/MsBibExportFormatTest4.xml | 0 .../exporter/MsBibExportFormatTest5.bib | 0 .../exporter/MsBibExportFormatTest5.xml | 0 .../exporter/MsBibExportFormatTest6.bib | 0 .../exporter/MsBibExportFormatTest6.xml | 0 .../exporter/MsBibExportFormatUmlauts.bib | 0 .../exporter/MsBibExportFormatUmlauts.xml | 0 .../jabref/{ => logic}/exporter/MsBibLCID.bib | 0 .../jabref/{ => logic}/exporter/MsBibLCID.xml | 0 .../{ => logic}/exporter/MsBibShorttitle.bib | 0 .../{ => logic}/exporter/MsBibShorttitle.xml | 0 81 files changed, 436 insertions(+), 421 deletions(-) delete mode 100644 src/main/java/net/sf/jabref/exporter/ExportFormats.java rename src/main/java/net/sf/jabref/{ => gui}/exporter/AutoSaveManager.java (93%) rename src/main/java/net/sf/jabref/{ => gui}/exporter/CustomExportDialog.java (99%) create mode 100644 src/main/java/net/sf/jabref/gui/exporter/ExportAction.java rename src/main/java/net/sf/jabref/{ => gui}/exporter/ExportCustomizationDialog.java (99%) rename src/main/java/net/sf/jabref/{ => gui}/exporter/ExportFileFilter.java (88%) rename src/main/java/net/sf/jabref/{ => gui}/exporter/ExportToClipboardAction.java (97%) rename src/main/java/net/sf/jabref/{ => gui}/exporter/RtfSelection.java (98%) rename src/main/java/net/sf/jabref/{ => gui}/exporter/SaveAllAction.java (98%) rename src/main/java/net/sf/jabref/{ => gui}/exporter/SaveDatabaseAction.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/BibDatabaseWriter.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/BibtexDatabaseWriter.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/CustomExportList.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/ExportComparator.java (96%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/ExportFormat.java (96%) create mode 100644 src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java rename src/main/java/net/sf/jabref/{ => logic}/exporter/FieldFormatterCleanups.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/FileSaveSession.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/IExportFormat.java (92%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/MSBibExportFormat.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/ModsExportFormat.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/OOCalcDatabase.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/OpenDocumentRepresentation.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/OpenDocumentSpreadsheetCreator.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/OpenOfficeDocumentCreator.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/SaveException.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/SavePreferences.java (99%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/SaveSession.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/StringSaveSession.java (98%) rename src/main/java/net/sf/jabref/{ => logic}/exporter/VerifyingWriter.java (98%) rename src/test/java/net/sf/jabref/{ => logic}/exporter/BibtexDatabaseWriterTest.java (99%) rename src/test/java/net/sf/jabref/{ => logic}/exporter/ExportFormatTest.java (98%) rename src/test/java/net/sf/jabref/{ => logic}/exporter/FieldFormatterCleanupsTest.java (99%) rename src/test/java/net/sf/jabref/{ => logic}/exporter/HtmlExportFormatTest.java (98%) rename src/test/java/net/sf/jabref/{ => logic}/exporter/MSBibExportFormatTestFiles.java (97%) rename src/test/java/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest.java (97%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest1.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest1.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest2.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest2.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest3.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest3.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest4.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest4.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest5.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest5.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest6.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatTest6.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatUmlauts.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibExportFormatUmlauts.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibLCID.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibLCID.xml (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibShorttitle.bib (100%) rename src/test/resources/net/sf/jabref/{ => logic}/exporter/MsBibShorttitle.xml (100%) diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index 2d9d5de98e44..c62681edd421 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -12,12 +12,12 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.BibtexDatabaseWriter; -import net.sf.jabref.exporter.SavePreferences; -import net.sf.jabref.exporter.StringSaveSession; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.importer.fileformat.ParseException; +import net.sf.jabref.logic.exporter.BibtexDatabaseWriter; +import net.sf.jabref.logic.exporter.SavePreferences; +import net.sf.jabref.logic.exporter.StringSaveSession; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.groups.GroupHierarchyType; import net.sf.jabref.logic.groups.KeywordGroup; diff --git a/src/main/java/net/sf/jabref/Globals.java b/src/main/java/net/sf/jabref/Globals.java index 7fb2cf06a5b9..c51932db8dbd 100644 --- a/src/main/java/net/sf/jabref/Globals.java +++ b/src/main/java/net/sf/jabref/Globals.java @@ -18,9 +18,9 @@ import java.util.Optional; import net.sf.jabref.collab.FileUpdateMonitor; -import net.sf.jabref.exporter.AutoSaveManager; import net.sf.jabref.gui.GlobalFocusListener; import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.exporter.AutoSaveManager; import net.sf.jabref.gui.keyboard.KeyBindingPreferences; import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.logic.error.StreamEavesdropper; diff --git a/src/main/java/net/sf/jabref/JabRefMain.java b/src/main/java/net/sf/jabref/JabRefMain.java index 93a4420e7e3a..e825a28a9172 100644 --- a/src/main/java/net/sf/jabref/JabRefMain.java +++ b/src/main/java/net/sf/jabref/JabRefMain.java @@ -20,9 +20,9 @@ import javax.swing.SwingUtilities; import net.sf.jabref.cli.ArgumentProcessor; -import net.sf.jabref.exporter.ExportFormats; import net.sf.jabref.gui.remote.JabRefMessageHandler; import net.sf.jabref.logic.CustomEntryTypesManager; +import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.ProxyAuthenticator; diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index 497210c35bd6..79cae1b39fcf 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -46,9 +46,6 @@ import javax.swing.JTable; import javax.swing.UIManager; -import net.sf.jabref.exporter.CustomExportList; -import net.sf.jabref.exporter.ExportComparator; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.external.DroppedFileHandler; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; @@ -58,6 +55,9 @@ import net.sf.jabref.logic.autocompleter.AutoCompletePreferences; import net.sf.jabref.logic.cleanup.CleanupPreset; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; +import net.sf.jabref.logic.exporter.CustomExportList; +import net.sf.jabref.logic.exporter.ExportComparator; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index c4247fc45115..de4646a45111 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -31,9 +31,9 @@ import java.util.TreeMap; import java.util.Vector; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.config.SaveOrderConfig; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.AbstractLabelPattern; diff --git a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java index 9a8b0d548bd5..f8212c7d3b02 100644 --- a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java @@ -19,14 +19,6 @@ import net.sf.jabref.JabRefGUI; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.BibDatabaseWriter; -import net.sf.jabref.exporter.BibtexDatabaseWriter; -import net.sf.jabref.exporter.ExportFormats; -import net.sf.jabref.exporter.FileSaveSession; -import net.sf.jabref.exporter.IExportFormat; -import net.sf.jabref.exporter.SaveException; -import net.sf.jabref.exporter.SavePreferences; -import net.sf.jabref.exporter.SaveSession; import net.sf.jabref.external.AutoSetLinks; import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.importer.ImportInspectionCommandLine; @@ -35,6 +27,14 @@ import net.sf.jabref.importer.fetcher.EntryFetcher; import net.sf.jabref.importer.fetcher.EntryFetchers; import net.sf.jabref.logic.CustomEntryTypesManager; +import net.sf.jabref.logic.exporter.BibDatabaseWriter; +import net.sf.jabref.logic.exporter.BibtexDatabaseWriter; +import net.sf.jabref.logic.exporter.ExportFormats; +import net.sf.jabref.logic.exporter.FileSaveSession; +import net.sf.jabref.logic.exporter.IExportFormat; +import net.sf.jabref.logic.exporter.SaveException; +import net.sf.jabref.logic.exporter.SavePreferences; +import net.sf.jabref.logic.exporter.SaveSession; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.logging.JabRefLogger; diff --git a/src/main/java/net/sf/jabref/cli/JabRefCLI.java b/src/main/java/net/sf/jabref/cli/JabRefCLI.java index 234b37a95f45..b7487365962d 100644 --- a/src/main/java/net/sf/jabref/cli/JabRefCLI.java +++ b/src/main/java/net/sf/jabref/cli/JabRefCLI.java @@ -16,7 +16,7 @@ package net.sf.jabref.cli; import net.sf.jabref.Globals; -import net.sf.jabref.exporter.ExportFormats; +import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.l10n.Localization; import org.apache.commons.cli.CommandLine; diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index f9966dc085eb..106fc148d10a 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -35,17 +35,17 @@ import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.BibDatabaseWriter; -import net.sf.jabref.exporter.BibtexDatabaseWriter; -import net.sf.jabref.exporter.FileSaveSession; -import net.sf.jabref.exporter.SaveException; -import net.sf.jabref.exporter.SavePreferences; -import net.sf.jabref.exporter.SaveSession; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.importer.OpenDatabaseAction; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.bibtex.comparator.EntryComparator; +import net.sf.jabref.logic.exporter.BibDatabaseWriter; +import net.sf.jabref.logic.exporter.BibtexDatabaseWriter; +import net.sf.jabref.logic.exporter.FileSaveSession; +import net.sf.jabref.logic.exporter.SaveException; +import net.sf.jabref.logic.exporter.SavePreferences; +import net.sf.jabref.logic.exporter.SaveSession; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.DuplicateCheck; diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormats.java b/src/main/java/net/sf/jabref/exporter/ExportFormats.java deleted file mode 100644 index d0d7959183b4..000000000000 --- a/src/main/java/net/sf/jabref/exporter/ExportFormats.java +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright (C) 2003-2016 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.exporter; - -import java.awt.event.ActionEvent; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.swing.filechooser.FileFilter; - -import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.JabRefFrame; -import net.sf.jabref.gui.actions.MnemonicAwareAction; -import net.sf.jabref.gui.worker.AbstractWorker; -import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class ExportFormats { - - private static final Log LOGGER = LogFactory.getLog(ExportFormats.class); - - private static final Map EXPORT_FORMATS = new TreeMap<>(); - - // Global variable that is used for counting output entries when exporting: - public static int entryNumber; - - - public static void initAllExports() { - - ExportFormats.EXPORT_FORMATS.clear(); - - // Initialize Build-In Export Formats - ExportFormats.putFormat(new ExportFormat("HTML", "html", "html", null, ".html")); - ExportFormats.putFormat(new ExportFormat(Localization.lang("Simple HTML"), "simplehtml", "simplehtml", null, ".html")); - ExportFormats.putFormat(new ExportFormat("DocBook 4.4", "docbook", "docbook", null, ".xml")); - ExportFormats.putFormat(new ExportFormat("DIN 1505", "din1505", "din1505winword", "din1505", ".rtf")); - ExportFormats.putFormat(new ExportFormat("BibTeXML", "bibtexml", "bibtexml", null, ".xml")); - ExportFormats.putFormat(new ExportFormat("BibO RDF", "bibordf", "bibordf", null, ".rdf")); - ExportFormats.putFormat(new ModsExportFormat()); - ExportFormats.putFormat(new ExportFormat(Localization.lang("HTML table"), "tablerefs", "tablerefs", "tablerefs", ".html")); - ExportFormats.putFormat(new ExportFormat(Localization.lang("HTML list"), - "listrefs", "listrefs", "listrefs", ".html")); - ExportFormats.putFormat(new ExportFormat(Localization.lang("HTML table (with Abstract & BibTeX)"), - "tablerefsabsbib", "tablerefsabsbib", "tablerefsabsbib", ".html")); - ExportFormats.putFormat(new ExportFormat("Harvard RTF", "harvard", "harvard", - "harvard", ".rtf")); - ExportFormats.putFormat(new ExportFormat("ISO 690", "iso690rtf", "iso690RTF", "iso690rtf", ".rtf")); - ExportFormats.putFormat(new ExportFormat("ISO 690", "iso690txt", "iso690", "iso690txt", ".txt")); - ExportFormats.putFormat(new ExportFormat("Endnote", "endnote", "EndNote", "endnote", ".txt")); - ExportFormats.putFormat(new ExportFormat("OpenOffice/LibreOffice CSV", "oocsv", "openoffice-csv", - "openoffice", ".csv")); - ExportFormat ef = new ExportFormat("RIS", "ris", "ris", "ris", ".ris"); - ef.setEncoding(StandardCharsets.UTF_8); - ExportFormats.putFormat(ef); - ExportFormats.putFormat(new ExportFormat("MIS Quarterly", "misq", "misq", "misq", ".rtf")); - - ExportFormats.putFormat(new OpenOfficeDocumentCreator()); - ExportFormats.putFormat(new OpenDocumentSpreadsheetCreator()); - ExportFormats.putFormat(new MSBibExportFormat()); - ExportFormats.putFormat(new ModsExportFormat()); - - // Now add custom export formats - Map customFormats = Globals.prefs.customExports.getCustomExportFormats(); - for (IExportFormat format : customFormats.values()) { - ExportFormats.putFormat(format); - } - } - - /** - * Build a string listing of all available export formats. - * - * @param maxLineLength - * The max line length before a line break must be added. - * @param linePrefix - * If a line break is added, this prefix will be inserted at the - * beginning of the next line. - * @return The string describing available formats. - */ - public static String getConsoleExportList(int maxLineLength, int firstLineSubtr, - String linePrefix) { - StringBuilder sb = new StringBuilder(); - int lastBreak = -firstLineSubtr; - - for (String name : ExportFormats.EXPORT_FORMATS.keySet()) { - if (((sb.length() + 2 + name.length()) - lastBreak) > maxLineLength) { - sb.append(",\n"); - lastBreak = sb.length(); - sb.append(linePrefix); - } else if (sb.length() > 0) { - sb.append(", "); - } - sb.append(name); - } - - return sb.toString(); - } - - /** - * Get a Map of all export formats. - * @return A Map containing all export formats, mapped to their console names. - */ - public static Map getExportFormats() { - // It is perhaps overly paranoid to make a defensive copy in this case: - return Collections.unmodifiableMap(ExportFormats.EXPORT_FORMATS); - } - - /** - * Look up the named export format. - * - * @param consoleName - * The export name given in the JabRef console help information. - * @return The ExportFormat, or null if no exportformat with that name is - * registered. - */ - public static IExportFormat getExportFormat(String consoleName) { - return ExportFormats.EXPORT_FORMATS.get(consoleName); - } - - /** - * Create an AbstractAction for performing an export operation. - * - * @param frame - * The JabRefFrame of this JabRef instance. - * @param selectedOnly - * true indicates that only selected entries should be exported, - * false indicates that all entries should be exported. - * @return The action. - */ - public static AbstractAction getExportAction(JabRefFrame frame, boolean selectedOnly) { - - class ExportAction extends MnemonicAwareAction { - - private final JabRefFrame frame; - - private final boolean selectedOnly; - - - public ExportAction(JabRefFrame frame, boolean selectedOnly) { - this.frame = frame; - this.selectedOnly = selectedOnly; - putValue(Action.NAME, selectedOnly ? Localization.menuTitle("Export selected entries") : - Localization.menuTitle("Export")); - } - - @Override - public void actionPerformed(ActionEvent e) { - ExportFormats.initAllExports(); - JFileChooser fc = ExportFormats.createExportFileChooser( - Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY)); - fc.showSaveDialog(frame); - File file = fc.getSelectedFile(); - if (file == null) { - return; - } - FileFilter ff = fc.getFileFilter(); - if (ff instanceof ExportFileFilter) { - - ExportFileFilter eff = (ExportFileFilter) ff; - String path = file.getPath(); - if (!path.endsWith(eff.getExtension())) { - path = path + eff.getExtension(); - } - file = new File(path); - if (file.exists()) { - // Warn that the file exists: - if (JOptionPane.showConfirmDialog(frame, - Localization.lang("'%0' exists. Overwrite file?", file.getName()), - Localization.lang("Export"), JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) { - return; - } - } - final IExportFormat format = eff.getExportFormat(); - List entries; - if (selectedOnly) { - // Selected entries - entries = frame.getCurrentBasePanel().getSelectedEntries(); - } else { - // All entries - entries = frame.getCurrentBasePanel().getDatabase().getEntries(); - } - - // Set the global variable for this database's file directory before exporting, - // so formatters can resolve linked files correctly. - // (This is an ugly hack!) - Globals.prefs.fileDirForDatabase = frame.getCurrentBasePanel().getBibDatabaseContext() - .getFileDirectory(); - - // Make sure we remember which filter was used, to set - // the default for next time: - Globals.prefs.put(JabRefPreferences.LAST_USED_EXPORT, format.getConsoleName()); - Globals.prefs.put(JabRefPreferences.EXPORT_WORKING_DIRECTORY, file.getParent()); - - final File finFile = file; - final List finEntries = entries; - AbstractWorker exportWorker = new AbstractWorker() { - - String errorMessage; - - - @Override - public void run() { - try { - format.performExport(frame.getCurrentBasePanel().getBibDatabaseContext(), - finFile.getPath(), - frame.getCurrentBasePanel().getBibDatabaseContext().getMetaData().getEncoding(), - finEntries); - } catch (Exception ex) { - LOGGER.warn("Problem exporting", ex); - if (ex.getMessage() == null) { - errorMessage = ex.toString(); - } else { - errorMessage = ex.getMessage(); - } - } - } - - @Override - public void update() { - // No error message. Report success: - if (errorMessage == null) { - frame.output(Localization.lang("%0 export successful", format.getDisplayName())); - } - // ... or show an error dialog: - else { - frame.output(Localization.lang("Could not save file.") - + " - " + errorMessage); - // Need to warn the user that saving failed! - JOptionPane.showMessageDialog(frame, Localization.lang("Could not save file.") - + "\n" + errorMessage, Localization.lang("Save database"), - JOptionPane.ERROR_MESSAGE); - } - } - }; - - // Run the export action in a background thread: - exportWorker.getWorker().run(); - // Run the update method: - exportWorker.update(); - } - } - } - - return new ExportAction(frame, selectedOnly); - } - - private static JFileChooser createExportFileChooser(String currentDir) { - String lastUsedFormat = Globals.prefs.get(JabRefPreferences.LAST_USED_EXPORT); - FileFilter defaultFilter = null; - JFileChooser fc = new JFileChooser(currentDir); - Set filters = new TreeSet<>(); - for (Map.Entry e : ExportFormats.EXPORT_FORMATS.entrySet()) { - String formatName = e.getKey(); - IExportFormat format = e.getValue(); - filters.add(format.getFileFilter()); - if (formatName.equals(lastUsedFormat)) { - defaultFilter = format.getFileFilter(); - } - } - for (FileFilter ff : filters) { - fc.addChoosableFileFilter(ff); - } - fc.setAcceptAllFileFilterUsed(false); - if (defaultFilter != null) { - fc.setFileFilter(defaultFilter); - } - return fc; - } - - private static void putFormat(IExportFormat format) { - ExportFormats.EXPORT_FORMATS.put(format.getConsoleName(), format); - } - -} diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index db900bd77cbb..8e65a47c2b72 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -63,13 +63,6 @@ import net.sf.jabref.collab.FileUpdatePanel; import net.sf.jabref.event.EntryAddedEvent; import net.sf.jabref.event.EntryChangedEvent; -import net.sf.jabref.exporter.BibtexDatabaseWriter; -import net.sf.jabref.exporter.ExportToClipboardAction; -import net.sf.jabref.exporter.FileSaveSession; -import net.sf.jabref.exporter.SaveDatabaseAction; -import net.sf.jabref.exporter.SaveException; -import net.sf.jabref.exporter.SavePreferences; -import net.sf.jabref.exporter.SaveSession; import net.sf.jabref.external.AttachFileAction; import net.sf.jabref.external.ExternalFileMenuItem; import net.sf.jabref.external.ExternalFileType; @@ -83,6 +76,8 @@ 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.exporter.ExportToClipboardAction; +import net.sf.jabref.gui.exporter.SaveDatabaseAction; import net.sf.jabref.gui.fieldeditors.FieldEditor; import net.sf.jabref.gui.groups.GroupAddRemoveDialog; import net.sf.jabref.gui.groups.GroupSelector; @@ -117,6 +112,11 @@ import net.sf.jabref.logic.autocompleter.AutoCompleter; import net.sf.jabref.logic.autocompleter.AutoCompleterFactory; import net.sf.jabref.logic.autocompleter.ContentAutoCompleters; +import net.sf.jabref.logic.exporter.BibtexDatabaseWriter; +import net.sf.jabref.logic.exporter.FileSaveSession; +import net.sf.jabref.logic.exporter.SaveException; +import net.sf.jabref.logic.exporter.SavePreferences; +import net.sf.jabref.logic.exporter.SaveSession; import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 6b43f4ef2962..4645e65ddcf3 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -74,11 +74,6 @@ import net.sf.jabref.HighlightMatchingGroupPreferences; import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.exporter.AutoSaveManager; -import net.sf.jabref.exporter.ExportCustomizationDialog; -import net.sf.jabref.exporter.ExportFormats; -import net.sf.jabref.exporter.SaveAllAction; -import net.sf.jabref.exporter.SaveDatabaseAction; import net.sf.jabref.external.ExternalFileTypeEditor; import net.sf.jabref.external.push.PushToApplicationButton; import net.sf.jabref.external.push.PushToApplications; @@ -96,6 +91,11 @@ import net.sf.jabref.gui.actions.SearchForUpdateAction; import net.sf.jabref.gui.actions.SortTabsAction; import net.sf.jabref.gui.dbproperties.DatabasePropertiesDialog; +import net.sf.jabref.gui.exporter.AutoSaveManager; +import net.sf.jabref.gui.exporter.ExportAction; +import net.sf.jabref.gui.exporter.ExportCustomizationDialog; +import net.sf.jabref.gui.exporter.SaveAllAction; +import net.sf.jabref.gui.exporter.SaveDatabaseAction; import net.sf.jabref.gui.groups.EntryTableTransferHandler; import net.sf.jabref.gui.groups.GroupSelector; import net.sf.jabref.gui.help.AboutAction; @@ -239,8 +239,8 @@ public class JabRefFrame extends JFrame implements OutputPrinter { private final AbstractAction saveSelectedAsPlain = new GeneralAction(Actions.SAVE_SELECTED_AS_PLAIN, Localization.menuTitle("Save selected as plain BibTeX..."), Localization.lang("Save selected as plain BibTeX...")); - private final AbstractAction exportAll = ExportFormats.getExportAction(this, false); - private final AbstractAction exportSelected = ExportFormats.getExportAction(this, true); + private final AbstractAction exportAll = ExportAction.getExportAction(this, false); + private final AbstractAction exportSelected = ExportAction.getExportAction(this, true); private final AbstractAction importCurrent = ImportFormats.getImportAction(this, false); private final AbstractAction importNew = ImportFormats.getImportAction(this, true); public final AbstractAction nextTab = new ChangeTabAction(true); diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index 0868f26f648f..a5e326a58158 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -51,10 +51,10 @@ import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.event.FieldChangedEvent; -import net.sf.jabref.exporter.ExportFormats; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.fieldeditors.PreviewPanelTransferHandler; import net.sf.jabref.gui.keyboard.KeyBinding; +import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.layout.LayoutHelper; diff --git a/src/main/java/net/sf/jabref/gui/cleanup/CleanupActionsListModel.java b/src/main/java/net/sf/jabref/gui/cleanup/CleanupActionsListModel.java index ecdd75297f05..280d508b9111 100644 --- a/src/main/java/net/sf/jabref/gui/cleanup/CleanupActionsListModel.java +++ b/src/main/java/net/sf/jabref/gui/cleanup/CleanupActionsListModel.java @@ -8,8 +8,8 @@ import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; public class CleanupActionsListModel implements ListModel { diff --git a/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java b/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java index f1fcee95994f..defbadce4de3 100644 --- a/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java +++ b/src/main/java/net/sf/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java @@ -41,8 +41,8 @@ import javax.swing.event.ListDataListener; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java b/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java index c96900b7bd36..4128bb4b587a 100644 --- a/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java +++ b/src/main/java/net/sf/jabref/gui/dbproperties/DatabasePropertiesDialog.java @@ -38,13 +38,13 @@ import net.sf.jabref.Globals; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.SaveOrderConfigDisplay; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.cleanup.FieldFormatterCleanupsPanel; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.config.SaveOrderConfig; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; diff --git a/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java b/src/main/java/net/sf/jabref/gui/exporter/AutoSaveManager.java similarity index 93% rename from src/main/java/net/sf/jabref/exporter/AutoSaveManager.java rename to src/main/java/net/sf/jabref/gui/exporter/AutoSaveManager.java index 6e62c22d6dac..a94d78e063fd 100644 --- a/src/main/java/net/sf/jabref/exporter/AutoSaveManager.java +++ b/src/main/java/net/sf/jabref/gui/exporter/AutoSaveManager.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.io.File; import java.util.Timer; @@ -23,6 +23,12 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.logic.exporter.BibDatabaseWriter; +import net.sf.jabref.logic.exporter.BibtexDatabaseWriter; +import net.sf.jabref.logic.exporter.FileSaveSession; +import net.sf.jabref.logic.exporter.SaveException; +import net.sf.jabref.logic.exporter.SavePreferences; +import net.sf.jabref.logic.exporter.SaveSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/exporter/CustomExportDialog.java b/src/main/java/net/sf/jabref/gui/exporter/CustomExportDialog.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/CustomExportDialog.java rename to src/main/java/net/sf/jabref/gui/exporter/CustomExportDialog.java index 489a69af8c84..f68817af2f2a 100644 --- a/src/main/java/net/sf/jabref/exporter/CustomExportDialog.java +++ b/src/main/java/net/sf/jabref/gui/exporter/CustomExportDialog.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.awt.BorderLayout; import java.awt.GridBagConstraints; diff --git a/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java b/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java new file mode 100644 index 000000000000..6686265d0356 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java @@ -0,0 +1,184 @@ +package net.sf.jabref.gui.exporter; + +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.actions.MnemonicAwareAction; +import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.logic.exporter.ExportFormats; +import net.sf.jabref.logic.exporter.IExportFormat; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.BibEntry; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ExportAction { + + private static final Log LOGGER = LogFactory.getLog(ExportAction.class); + + + /** + * Create an AbstractAction for performing an export operation. + * + * @param frame + * The JabRefFrame of this JabRef instance. + * @param selectedOnly + * true indicates that only selected entries should be exported, + * false indicates that all entries should be exported. + * @return The action. + */ + public static AbstractAction getExportAction(JabRefFrame frame, boolean selectedOnly) { + + class InternalExportAction extends MnemonicAwareAction { + + private final JabRefFrame frame; + + private final boolean selectedOnly; + + + public InternalExportAction(JabRefFrame frame, boolean selectedOnly) { + this.frame = frame; + this.selectedOnly = selectedOnly; + putValue(Action.NAME, selectedOnly ? Localization.menuTitle("Export selected entries") : Localization + .menuTitle("Export")); + } + + @Override + public void actionPerformed(ActionEvent e) { + ExportFormats.initAllExports(); + JFileChooser fc = ExportAction + .createExportFileChooser(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY)); + fc.showSaveDialog(frame); + File file = fc.getSelectedFile(); + if (file == null) { + return; + } + FileFilter ff = fc.getFileFilter(); + if (ff instanceof ExportFileFilter) { + + ExportFileFilter eff = (ExportFileFilter) ff; + String path = file.getPath(); + if (!path.endsWith(eff.getExtension())) { + path = path + eff.getExtension(); + } + file = new File(path); + if (file.exists()) { + // Warn that the file exists: + if (JOptionPane.showConfirmDialog(frame, + Localization.lang("'%0' exists. Overwrite file?", file.getName()), + Localization.lang("Export"), JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) { + return; + } + } + final IExportFormat format = eff.getExportFormat(); + List entries; + if (selectedOnly) { + // Selected entries + entries = frame.getCurrentBasePanel().getSelectedEntries(); + } else { + // All entries + entries = frame.getCurrentBasePanel().getDatabase().getEntries(); + } + + // Set the global variable for this database's file directory before exporting, + // so formatters can resolve linked files correctly. + // (This is an ugly hack!) + Globals.prefs.fileDirForDatabase = frame.getCurrentBasePanel().getBibDatabaseContext() + .getFileDirectory(); + + // Make sure we remember which filter was used, to set + // the default for next time: + Globals.prefs.put(JabRefPreferences.LAST_USED_EXPORT, format.getConsoleName()); + Globals.prefs.put(JabRefPreferences.EXPORT_WORKING_DIRECTORY, file.getParent()); + + final File finFile = file; + final List finEntries = entries; + AbstractWorker exportWorker = new AbstractWorker() { + + String errorMessage; + + + @Override + public void run() { + try { + format.performExport(frame.getCurrentBasePanel().getBibDatabaseContext(), + finFile.getPath(), + frame.getCurrentBasePanel().getBibDatabaseContext().getMetaData().getEncoding(), + finEntries); + } catch (Exception ex) { + LOGGER.warn("Problem exporting", ex); + if (ex.getMessage() == null) { + errorMessage = ex.toString(); + } else { + errorMessage = ex.getMessage(); + } + } + } + + @Override + public void update() { + // No error message. Report success: + if (errorMessage == null) { + frame.output(Localization.lang("%0 export successful", format.getDisplayName())); + } + // ... or show an error dialog: + else { + frame.output(Localization.lang("Could not save file.") + " - " + errorMessage); + // Need to warn the user that saving failed! + JOptionPane.showMessageDialog(frame, + Localization.lang("Could not save file.") + "\n" + errorMessage, + Localization.lang("Save database"), JOptionPane.ERROR_MESSAGE); + } + } + }; + + // Run the export action in a background thread: + exportWorker.getWorker().run(); + // Run the update method: + exportWorker.update(); + } + } + } + + return new InternalExportAction(frame, selectedOnly); + } + + private static JFileChooser createExportFileChooser(String currentDir) { + String lastUsedFormat = Globals.prefs.get(JabRefPreferences.LAST_USED_EXPORT); + FileFilter defaultFilter = null; + JFileChooser fc = new JFileChooser(currentDir); + Set filters = new TreeSet<>(); + for (Map.Entry e : ExportFormats.getExportFormats().entrySet()) { + String formatName = e.getKey(); + IExportFormat format = e.getValue(); + ExportFileFilter exportFileFilter = new ExportFileFilter(format); + filters.add(exportFileFilter); + if (formatName.equals(lastUsedFormat)) { + defaultFilter = exportFileFilter; + } + } + for (FileFilter ff : filters) { + fc.addChoosableFileFilter(ff); + } + fc.setAcceptAllFileFilterUsed(false); + if (defaultFilter != null) { + fc.setFileFilter(defaultFilter); + } + return fc; + } + +} diff --git a/src/main/java/net/sf/jabref/exporter/ExportCustomizationDialog.java b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/ExportCustomizationDialog.java rename to src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java index f9a0edc299da..38ba30fbe58b 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.awt.BorderLayout; import java.awt.Dimension; diff --git a/src/main/java/net/sf/jabref/exporter/ExportFileFilter.java b/src/main/java/net/sf/jabref/gui/exporter/ExportFileFilter.java similarity index 88% rename from src/main/java/net/sf/jabref/exporter/ExportFileFilter.java rename to src/main/java/net/sf/jabref/gui/exporter/ExportFileFilter.java index fd7d576f48e8..6361316c699a 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFileFilter.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportFileFilter.java @@ -13,26 +13,28 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.io.File; import javax.swing.filechooser.FileFilter; +import net.sf.jabref.logic.exporter.IExportFormat; + /** * File filter that lets the user choose export format while choosing file to * export to. Contains a reference to the ExportFormat in question. */ -class ExportFileFilter extends FileFilter implements Comparable { +public class ExportFileFilter extends FileFilter implements Comparable { private final IExportFormat format; private final String extension; private final String name; - public ExportFileFilter(IExportFormat format, String extension) { + public ExportFileFilter(IExportFormat format) { this.format = format; - this.extension = extension; + this.extension = format.getExtension(); this.name = format.getDisplayName() + " (*" + extension + ')'; } diff --git a/src/main/java/net/sf/jabref/exporter/ExportToClipboardAction.java b/src/main/java/net/sf/jabref/gui/exporter/ExportToClipboardAction.java similarity index 97% rename from src/main/java/net/sf/jabref/exporter/ExportToClipboardAction.java rename to src/main/java/net/sf/jabref/gui/exporter/ExportToClipboardAction.java index b3585157b48f..fe950b8bc7e3 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportToClipboardAction.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportToClipboardAction.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.awt.Toolkit; import java.awt.datatransfer.ClipboardOwner; @@ -35,6 +35,8 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.logic.exporter.ExportFormats; +import net.sf.jabref.logic.exporter.IExportFormat; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/exporter/RtfSelection.java b/src/main/java/net/sf/jabref/gui/exporter/RtfSelection.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/RtfSelection.java rename to src/main/java/net/sf/jabref/gui/exporter/RtfSelection.java index f4a6512c6063..8306860b279c 100644 --- a/src/main/java/net/sf/jabref/exporter/RtfSelection.java +++ b/src/main/java/net/sf/jabref/gui/exporter/RtfSelection.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; diff --git a/src/main/java/net/sf/jabref/exporter/SaveAllAction.java b/src/main/java/net/sf/jabref/gui/exporter/SaveAllAction.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/SaveAllAction.java rename to src/main/java/net/sf/jabref/gui/exporter/SaveAllAction.java index 84b83cc52b19..4394d5e92e51 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveAllAction.java +++ b/src/main/java/net/sf/jabref/gui/exporter/SaveAllAction.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.awt.event.ActionEvent; diff --git a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/gui/exporter/SaveDatabaseAction.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java rename to src/main/java/net/sf/jabref/gui/exporter/SaveDatabaseAction.java index f7245aebcd9c..fb4f516716b8 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/gui/exporter/SaveDatabaseAction.java @@ -14,7 +14,7 @@ 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.exporter; +package net.sf.jabref.gui.exporter; import java.io.File; import java.io.IOException; @@ -37,6 +37,11 @@ import net.sf.jabref.gui.worker.AbstractWorker; import net.sf.jabref.gui.worker.CallBack; import net.sf.jabref.gui.worker.Worker; +import net.sf.jabref.logic.exporter.BibtexDatabaseWriter; +import net.sf.jabref.logic.exporter.FileSaveSession; +import net.sf.jabref.logic.exporter.SaveException; +import net.sf.jabref.logic.exporter.SavePreferences; +import net.sf.jabref.logic.exporter.SaveSession; import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileBasedLock; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java index 84d9f5bd31fe..7cf910aa5cba 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java @@ -41,12 +41,12 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.JabRefPreferencesFilter; import net.sf.jabref.JabRefPreferencesFilterDialog; -import net.sf.jabref.exporter.ExportFormats; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.keyboard.KeyBinder; import net.sf.jabref.gui.maintable.MainTable; +import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.l10n.Localization; import com.jgoodies.forms.builder.ButtonBarBuilder; diff --git a/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java b/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java index e3c678fc365b..a74e0ecb9a0f 100644 --- a/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java +++ b/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java @@ -26,10 +26,10 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.exporter.AutoSaveManager; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.ParserResultWarningDialog; +import net.sf.jabref.gui.exporter.AutoSaveManager; import net.sf.jabref.logic.l10n.Localization; /** diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index 4777284a30e1..5c73a0c625bb 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -36,13 +36,13 @@ import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.AutoSaveManager; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.ParserResultWarningDialog; import net.sf.jabref.gui.actions.MnemonicAwareAction; +import net.sf.jabref.gui.exporter.AutoSaveManager; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.importer.fileformat.BibtexImporter; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java index b0ed7b6fa3d5..e90c3f1c32b3 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java @@ -20,7 +20,7 @@ import java.util.Set; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.exporter.FieldFormatterCleanups; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; public class CleanupPreset { diff --git a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/logic/exporter/BibDatabaseWriter.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java rename to src/main/java/net/sf/jabref/logic/exporter/BibDatabaseWriter.java index 0b06ee4bb416..f8d74d2f6067 100644 --- a/src/main/java/net/sf/jabref/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/logic/exporter/BibDatabaseWriter.java @@ -14,8 +14,7 @@ * 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.IOException; import java.nio.charset.Charset; diff --git a/src/main/java/net/sf/jabref/exporter/BibtexDatabaseWriter.java b/src/main/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriter.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/BibtexDatabaseWriter.java rename to src/main/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriter.java index abd599c977a7..1141323cf3b8 100644 --- a/src/main/java/net/sf/jabref/exporter/BibtexDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriter.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.IOException; import java.io.Writer; diff --git a/src/main/java/net/sf/jabref/exporter/CustomExportList.java b/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/CustomExportList.java rename to src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java index ba0091b1c850..f4af48464b3b 100644 --- a/src/main/java/net/sf/jabref/exporter/CustomExportList.java +++ b/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.util.Comparator; import java.util.List; diff --git a/src/main/java/net/sf/jabref/exporter/ExportComparator.java b/src/main/java/net/sf/jabref/logic/exporter/ExportComparator.java similarity index 96% rename from src/main/java/net/sf/jabref/exporter/ExportComparator.java rename to src/main/java/net/sf/jabref/logic/exporter/ExportComparator.java index 46830f0c5b21..ed4082ee8165 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportComparator.java +++ b/src/main/java/net/sf/jabref/logic/exporter/ExportComparator.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.util.Comparator; import java.util.List; diff --git a/src/main/java/net/sf/jabref/exporter/ExportFormat.java b/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java similarity index 96% rename from src/main/java/net/sf/jabref/exporter/ExportFormat.java rename to src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java index 97475878f7e8..4cb6ba4a357d 100644 --- a/src/main/java/net/sf/jabref/exporter/ExportFormat.java +++ b/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.File; import java.io.FileNotFoundException; @@ -31,8 +31,6 @@ import java.util.Map; import java.util.Objects; -import javax.swing.filechooser.FileFilter; - import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.Layout; @@ -55,7 +53,6 @@ public class ExportFormat implements IExportFormat { private Charset encoding; // If this value is set, it will be used to override // the default encoding for the getCurrentBasePanel. - private FileFilter fileFilter; private boolean customExport; private static final String LAYOUT_PREFIX = "/resource/layout/"; @@ -123,6 +120,14 @@ public void setEncoding(Charset encoding) { this.encoding = encoding; } + /** + * @see IExportFormat#getExtension() + */ + @Override + public String getExtension() { + return extension; + } + /** * This method should return a reader from which the given layout file can * be read. @@ -177,7 +182,7 @@ private Reader getReader(String filename) throws IOException { * @throws IOException if a problem occurred while trying to write to {@code writer} * or read from required resources. * @throws Exception if any other error occurred during export. - * @see net.sf.jabref.exporter.IExportFormat#performExport(BibDatabaseContext, String, Charset, List) + * @see net.sf.jabref.logic.exporter.IExportFormat#performExport(BibDatabaseContext, String, Charset, List) */ @Override public void performExport(final BibDatabaseContext databaseContext, final String file, @@ -359,17 +364,6 @@ private static Map readFormatterFile(String lfFileName) { return formatters; } - /** - * @see net.sf.jabref.exporter.IExportFormat#getFileFilter() - */ - @Override - public FileFilter getFileFilter() { - if (fileFilter == null) { - fileFilter = new ExportFileFilter(this, extension); - } - return fileFilter; - } - public void finalizeSaveSession(final SaveSession ss, Path file) throws SaveException, IOException { ss.getWriter().flush(); ss.getWriter().close(); diff --git a/src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java b/src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java new file mode 100644 index 000000000000..f5b1de8a3eaa --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java @@ -0,0 +1,130 @@ +/* Copyright (C) 2003-2016 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.exporter; + +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +import net.sf.jabref.Globals; +import net.sf.jabref.logic.l10n.Localization; + +public class ExportFormats { + + private static final Map EXPORT_FORMATS = new TreeMap<>(); + + // Global variable that is used for counting output entries when exporting: + public static int entryNumber; + + + public static void initAllExports() { + + ExportFormats.EXPORT_FORMATS.clear(); + + // Initialize Build-In Export Formats + ExportFormats.putFormat(new ExportFormat("HTML", "html", "html", null, ".html")); + ExportFormats.putFormat(new ExportFormat(Localization.lang("Simple HTML"), "simplehtml", "simplehtml", null, ".html")); + ExportFormats.putFormat(new ExportFormat("DocBook 4.4", "docbook", "docbook", null, ".xml")); + ExportFormats.putFormat(new ExportFormat("DIN 1505", "din1505", "din1505winword", "din1505", ".rtf")); + ExportFormats.putFormat(new ExportFormat("BibTeXML", "bibtexml", "bibtexml", null, ".xml")); + ExportFormats.putFormat(new ExportFormat("BibO RDF", "bibordf", "bibordf", null, ".rdf")); + ExportFormats.putFormat(new ModsExportFormat()); + ExportFormats.putFormat(new ExportFormat(Localization.lang("HTML table"), "tablerefs", "tablerefs", "tablerefs", ".html")); + ExportFormats.putFormat(new ExportFormat(Localization.lang("HTML list"), + "listrefs", "listrefs", "listrefs", ".html")); + ExportFormats.putFormat(new ExportFormat(Localization.lang("HTML table (with Abstract & BibTeX)"), + "tablerefsabsbib", "tablerefsabsbib", "tablerefsabsbib", ".html")); + ExportFormats.putFormat(new ExportFormat("Harvard RTF", "harvard", "harvard", + "harvard", ".rtf")); + ExportFormats.putFormat(new ExportFormat("ISO 690", "iso690rtf", "iso690RTF", "iso690rtf", ".rtf")); + ExportFormats.putFormat(new ExportFormat("ISO 690", "iso690txt", "iso690", "iso690txt", ".txt")); + ExportFormats.putFormat(new ExportFormat("Endnote", "endnote", "EndNote", "endnote", ".txt")); + ExportFormats.putFormat(new ExportFormat("OpenOffice/LibreOffice CSV", "oocsv", "openoffice-csv", + "openoffice", ".csv")); + ExportFormat ef = new ExportFormat("RIS", "ris", "ris", "ris", ".ris"); + ef.setEncoding(StandardCharsets.UTF_8); + ExportFormats.putFormat(ef); + ExportFormats.putFormat(new ExportFormat("MIS Quarterly", "misq", "misq", "misq", ".rtf")); + + ExportFormats.putFormat(new OpenOfficeDocumentCreator()); + ExportFormats.putFormat(new OpenDocumentSpreadsheetCreator()); + ExportFormats.putFormat(new MSBibExportFormat()); + ExportFormats.putFormat(new ModsExportFormat()); + + // Now add custom export formats + Map customFormats = Globals.prefs.customExports.getCustomExportFormats(); + for (IExportFormat format : customFormats.values()) { + ExportFormats.putFormat(format); + } + } + + /** + * Build a string listing of all available export formats. + * + * @param maxLineLength + * The max line length before a line break must be added. + * @param linePrefix + * If a line break is added, this prefix will be inserted at the + * beginning of the next line. + * @return The string describing available formats. + */ + public static String getConsoleExportList(int maxLineLength, int firstLineSubtr, + String linePrefix) { + StringBuilder sb = new StringBuilder(); + int lastBreak = -firstLineSubtr; + + for (String name : ExportFormats.EXPORT_FORMATS.keySet()) { + if (((sb.length() + 2 + name.length()) - lastBreak) > maxLineLength) { + sb.append(",\n"); + lastBreak = sb.length(); + sb.append(linePrefix); + } else if (sb.length() > 0) { + sb.append(", "); + } + sb.append(name); + } + + return sb.toString(); + } + + /** + * Get a Map of all export formats. + * @return A Map containing all export formats, mapped to their console names. + */ + public static Map getExportFormats() { + // It is perhaps overly paranoid to make a defensive copy in this case: + return Collections.unmodifiableMap(ExportFormats.EXPORT_FORMATS); + } + + /** + * Look up the named export format. + * + * @param consoleName + * The export name given in the JabRef console help information. + * @return The ExportFormat, or null if no exportformat with that name is + * registered. + */ + public static IExportFormat getExportFormat(String consoleName) { + return ExportFormats.EXPORT_FORMATS.get(consoleName); + } + + + private static void putFormat(IExportFormat format) { + ExportFormats.EXPORT_FORMATS.put(format.getConsoleName(), format); + } + +} diff --git a/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java b/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java rename to src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java index dcb44ddc88cd..2b18076d37eb 100644 --- a/src/main/java/net/sf/jabref/exporter/FieldFormatterCleanups.java +++ b/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/net/sf/jabref/exporter/FileSaveSession.java b/src/main/java/net/sf/jabref/logic/exporter/FileSaveSession.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/FileSaveSession.java rename to src/main/java/net/sf/jabref/logic/exporter/FileSaveSession.java index 9530b6fbe043..eee1a54b91af 100644 --- a/src/main/java/net/sf/jabref/exporter/FileSaveSession.java +++ b/src/main/java/net/sf/jabref/logic/exporter/FileSaveSession.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -54,7 +54,7 @@ public class FileSaveSession extends SaveSession { private static final String TEMP_PREFIX = "jabref"; private static final String TEMP_SUFFIX = "save.bib"; private final boolean useLockFile; - private Path temporaryFile; + private final Path temporaryFile; public FileSaveSession(Charset encoding, boolean backup) throws SaveException { this(encoding, backup, createTemporaryFile()); diff --git a/src/main/java/net/sf/jabref/exporter/IExportFormat.java b/src/main/java/net/sf/jabref/logic/exporter/IExportFormat.java similarity index 92% rename from src/main/java/net/sf/jabref/exporter/IExportFormat.java rename to src/main/java/net/sf/jabref/logic/exporter/IExportFormat.java index 98e19f73b676..ced4d983a944 100644 --- a/src/main/java/net/sf/jabref/exporter/IExportFormat.java +++ b/src/main/java/net/sf/jabref/logic/exporter/IExportFormat.java @@ -13,14 +13,12 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.nio.charset.Charset; import java.nio.file.Path; import java.util.List; -import javax.swing.filechooser.FileFilter; - import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.model.entry.BibEntry; @@ -37,10 +35,7 @@ public interface IExportFormat { */ String getDisplayName(); - /** - * A file filter that accepts filetypes that this exporter would create. - */ - FileFilter getFileFilter(); + String getExtension(); /** * Perform the export. diff --git a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java b/src/main/java/net/sf/jabref/logic/exporter/MSBibExportFormat.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java rename to src/main/java/net/sf/jabref/logic/exporter/MSBibExportFormat.java index f33852aec1be..ee17ff813ad1 100644 --- a/src/main/java/net/sf/jabref/exporter/MSBibExportFormat.java +++ b/src/main/java/net/sf/jabref/logic/exporter/MSBibExportFormat.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.IOException; import java.nio.charset.Charset; diff --git a/src/main/java/net/sf/jabref/exporter/ModsExportFormat.java b/src/main/java/net/sf/jabref/logic/exporter/ModsExportFormat.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/ModsExportFormat.java rename to src/main/java/net/sf/jabref/logic/exporter/ModsExportFormat.java index b43f079a622a..04308883bdb8 100644 --- a/src/main/java/net/sf/jabref/exporter/ModsExportFormat.java +++ b/src/main/java/net/sf/jabref/logic/exporter/ModsExportFormat.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.IOException; import java.nio.charset.Charset; diff --git a/src/main/java/net/sf/jabref/exporter/OOCalcDatabase.java b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/OOCalcDatabase.java rename to src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java index 9c4a34ead008..be761efcf0fe 100644 --- a/src/main/java/net/sf/jabref/exporter/OOCalcDatabase.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/net/sf/jabref/exporter/OpenDocumentRepresentation.java b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/OpenDocumentRepresentation.java rename to src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java index b03e6daa0b1c..2cd3c68b5c28 100644 --- a/src/main/java/net/sf/jabref/exporter/OpenDocumentRepresentation.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/net/sf/jabref/exporter/OpenDocumentSpreadsheetCreator.java b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentSpreadsheetCreator.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/OpenDocumentSpreadsheetCreator.java rename to src/main/java/net/sf/jabref/logic/exporter/OpenDocumentSpreadsheetCreator.java index 56960af0bbe7..62e4a25df217 100644 --- a/src/main/java/net/sf/jabref/exporter/OpenDocumentSpreadsheetCreator.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentSpreadsheetCreator.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; diff --git a/src/main/java/net/sf/jabref/exporter/OpenOfficeDocumentCreator.java b/src/main/java/net/sf/jabref/logic/exporter/OpenOfficeDocumentCreator.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/OpenOfficeDocumentCreator.java rename to src/main/java/net/sf/jabref/logic/exporter/OpenOfficeDocumentCreator.java index 2a104480d3b6..ce0668a30c61 100644 --- a/src/main/java/net/sf/jabref/exporter/OpenOfficeDocumentCreator.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OpenOfficeDocumentCreator.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; diff --git a/src/main/java/net/sf/jabref/exporter/SaveException.java b/src/main/java/net/sf/jabref/logic/exporter/SaveException.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/SaveException.java rename to src/main/java/net/sf/jabref/logic/exporter/SaveException.java index c2597d6c55d3..0c4d6143a43e 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveException.java +++ b/src/main/java/net/sf/jabref/logic/exporter/SaveException.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/exporter/SavePreferences.java b/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java similarity index 99% rename from src/main/java/net/sf/jabref/exporter/SavePreferences.java rename to src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java index 5230f1953b97..0d0b52db800f 100644 --- a/src/main/java/net/sf/jabref/exporter/SavePreferences.java +++ b/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.nio.charset.Charset; diff --git a/src/main/java/net/sf/jabref/exporter/SaveSession.java b/src/main/java/net/sf/jabref/logic/exporter/SaveSession.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/SaveSession.java rename to src/main/java/net/sf/jabref/logic/exporter/SaveSession.java index 57898db111dd..6b95ac4e9079 100644 --- a/src/main/java/net/sf/jabref/exporter/SaveSession.java +++ b/src/main/java/net/sf/jabref/logic/exporter/SaveSession.java @@ -15,7 +15,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.nio.charset.Charset; import java.nio.file.Path; diff --git a/src/main/java/net/sf/jabref/exporter/StringSaveSession.java b/src/main/java/net/sf/jabref/logic/exporter/StringSaveSession.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/StringSaveSession.java rename to src/main/java/net/sf/jabref/logic/exporter/StringSaveSession.java index 3fec5c30f30b..fbdc4d9a4f2c 100644 --- a/src/main/java/net/sf/jabref/exporter/StringSaveSession.java +++ b/src/main/java/net/sf/jabref/logic/exporter/StringSaveSession.java @@ -15,7 +15,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/src/main/java/net/sf/jabref/exporter/VerifyingWriter.java b/src/main/java/net/sf/jabref/logic/exporter/VerifyingWriter.java similarity index 98% rename from src/main/java/net/sf/jabref/exporter/VerifyingWriter.java rename to src/main/java/net/sf/jabref/logic/exporter/VerifyingWriter.java index 8a40ccd72444..4f636e345ab6 100644 --- a/src/main/java/net/sf/jabref/exporter/VerifyingWriter.java +++ b/src/main/java/net/sf/jabref/logic/exporter/VerifyingWriter.java @@ -13,7 +13,7 @@ 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.exporter; +package net.sf.jabref.logic.exporter; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java index 905b2ad6e158..c0cbba8d536b 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java @@ -40,7 +40,7 @@ public class GroupTreeNode extends TreeNode { * * @param group the group underlying this node */ - private GroupTreeNode(AbstractGroup group) { + public GroupTreeNode(AbstractGroup group) { super(GroupTreeNode.class); setGroup(group); } @@ -85,7 +85,7 @@ public Optional setGroup(AbstractGroup newGroup, boolean sho if (shouldKeepPreviousAssignments && newGroup.supportsAdd()) { List entriesMatchedByOldGroup = entriesInDatabase.stream().filter(oldGroup::isMatch) .collect(Collectors.toList()); - if (oldGroup instanceof ExplicitGroup && newGroup instanceof ExplicitGroup) { + if ((oldGroup instanceof ExplicitGroup) && (newGroup instanceof ExplicitGroup)) { // Rename of explicit group, so remove old group assignment oldGroup.remove(entriesMatchedByOldGroup); } @@ -170,7 +170,7 @@ public boolean equals(Object o) { if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if ((o == null) || (getClass() != o.getClass())) { return false; } GroupTreeNode that = (GroupTreeNode) o; diff --git a/src/main/java/net/sf/jabref/logic/layout/format/Number.java b/src/main/java/net/sf/jabref/logic/layout/format/Number.java index 238eb50b0701..71f8998cde2d 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/Number.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/Number.java @@ -15,7 +15,7 @@ */ package net.sf.jabref.logic.layout.format; -import net.sf.jabref.exporter.ExportFormats; +import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.layout.ParamLayoutFormatter; /** diff --git a/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java b/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java index 24cc5990faa6..644ccdf04236 100644 --- a/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java +++ b/src/main/java/net/sf/jabref/sql/exporter/DatabaseExporter.java @@ -30,9 +30,9 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.exporter.BibDatabaseWriter; -import net.sf.jabref.exporter.SavePreferences; import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.logic.exporter.BibDatabaseWriter; +import net.sf.jabref.logic.exporter.SavePreferences; import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.AllEntriesGroup; import net.sf.jabref.logic.groups.ExplicitGroup; diff --git a/src/test/java/net/sf/jabref/MetaDataTest.java b/src/test/java/net/sf/jabref/MetaDataTest.java index 81fb660887d8..a0c7d9450b50 100644 --- a/src/test/java/net/sf/jabref/MetaDataTest.java +++ b/src/test/java/net/sf/jabref/MetaDataTest.java @@ -4,8 +4,8 @@ import java.util.Map; import java.util.TreeMap; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.casechanger.LowerCaseFormatter; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/cleanup/CleanupActionsListModelTest.java b/src/test/java/net/sf/jabref/cleanup/CleanupActionsListModelTest.java index 9252e726c9a4..d15e7ab4d42b 100644 --- a/src/test/java/net/sf/jabref/cleanup/CleanupActionsListModelTest.java +++ b/src/test/java/net/sf/jabref/cleanup/CleanupActionsListModelTest.java @@ -8,9 +8,9 @@ import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.gui.cleanup.CleanupActionsListModel; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.bibtexfields.ClearFormatter; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java index adc87ca23425..29b0fef3e8ff 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java @@ -14,10 +14,10 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.exporter.FieldFormatterCleanups; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.config.SaveOrderConfig; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.casechanger.LowerCaseFormatter; import net.sf.jabref.logic.groups.AllEntriesGroup; import net.sf.jabref.logic.groups.ExplicitGroup; diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index 25a6eed16a49..30bc897ee927 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -11,7 +11,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; -import net.sf.jabref.exporter.FieldFormatterCleanups; +import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; diff --git a/src/test/java/net/sf/jabref/exporter/BibtexDatabaseWriterTest.java b/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java similarity index 99% rename from src/test/java/net/sf/jabref/exporter/BibtexDatabaseWriterTest.java rename to src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java index e9cd0d576629..f5cce9ba6c6c 100644 --- a/src/test/java/net/sf/jabref/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -1,6 +1,5 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; -import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Path; @@ -49,7 +48,7 @@ public class BibtexDatabaseWriterTest { private BibDatabaseContext bibtexContext; @Before - public void setUp() throws SaveException, IOException { + public void setUp() { Globals.prefs = JabRefPreferences.getInstance(); // Write to a string instead of to a file diff --git a/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java similarity index 98% rename from src/test/java/net/sf/jabref/exporter/ExportFormatTest.java rename to src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java index 17c1d0d36363..56c0a0137150 100644 --- a/src/test/java/net/sf/jabref/exporter/ExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.io.File; import java.nio.charset.Charset; diff --git a/src/test/java/net/sf/jabref/exporter/FieldFormatterCleanupsTest.java b/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java similarity index 99% rename from src/test/java/net/sf/jabref/exporter/FieldFormatterCleanupsTest.java rename to src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java index f1d7a8617541..16122e70dda0 100644 --- a/src/test/java/net/sf/jabref/exporter/FieldFormatterCleanupsTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.util.Arrays; import java.util.Collections; diff --git a/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java similarity index 98% rename from src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java rename to src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java index d72385d23c02..14749370112f 100644 --- a/src/test/java/net/sf/jabref/exporter/HtmlExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.io.File; import java.nio.charset.Charset; diff --git a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java b/src/test/java/net/sf/jabref/logic/exporter/MSBibExportFormatTestFiles.java similarity index 97% rename from src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java rename to src/test/java/net/sf/jabref/logic/exporter/MSBibExportFormatTestFiles.java index c113d6190f35..b9ce27ac87f6 100644 --- a/src/test/java/net/sf/jabref/exporter/MSBibExportFormatTestFiles.java +++ b/src/test/java/net/sf/jabref/logic/exporter/MSBibExportFormatTestFiles.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.io.File; import java.io.IOException; @@ -42,7 +42,7 @@ public class MSBibExportFormatTestFiles { public MSBibExportFormat msBibExportFormat; public BibtexImporter testImporter; - public static final String PATH_TO_FILE = "src/test/resources/net/sf/jabref/exporter/"; + public static final String PATH_TO_FILE = "src/test/resources/net/sf/jabref/logic/exporter/"; @Parameter public String filename; diff --git a/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/MsBibExportFormatTest.java similarity index 97% rename from src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java rename to src/test/java/net/sf/jabref/logic/exporter/MsBibExportFormatTest.java index ffecbf00c36b..977541ffc1a7 100644 --- a/src/test/java/net/sf/jabref/exporter/MsBibExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/MsBibExportFormatTest.java @@ -1,4 +1,4 @@ -package net.sf.jabref.exporter; +package net.sf.jabref.logic.exporter; import java.io.File; import java.io.IOException; diff --git a/src/test/java/net/sf/jabref/logic/openoffice/CitationEntryTest.java b/src/test/java/net/sf/jabref/logic/openoffice/CitationEntryTest.java index 36faf50d22b4..4f4c53cfe3e9 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/CitationEntryTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/CitationEntryTest.java @@ -80,7 +80,6 @@ public void testCitationEntryCompareTo() { CitationEntry citationEntry1 = new CitationEntry("RefMark", "Context", "Info"); CitationEntry citationEntry2 = new CitationEntry("RefMark2", "Context", "Info"); CitationEntry citationEntry3 = new CitationEntry("RefMark", "Other Context", "Other Info"); - assertEquals(0, citationEntry1.compareTo(citationEntry1)); assertEquals(0, citationEntry1.compareTo(citationEntry3)); assertEquals(-1, citationEntry1.compareTo(citationEntry2)); assertEquals(1, citationEntry2.compareTo(citationEntry1)); diff --git a/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java b/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java index 859e2ce84a67..67fb40205934 100644 --- a/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java +++ b/src/test/java/net/sf/jabref/model/entry/AuthorListTest.java @@ -31,8 +31,8 @@ public void testFixAuthorNatbib() { public void testGetAuthorList() { // Test caching in authorCache. AuthorList al = AuthorList.parse("John Smith"); - Assert.assertTrue(al == AuthorList.parse("John Smith")); - Assert.assertFalse(al == AuthorList.parse("Smith")); + Assert.assertEquals(al, AuthorList.parse("John Smith")); + Assert.assertFalse(al.equals(AuthorList.parse("Smith"))); } @SuppressWarnings("unused") diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest1.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest1.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest1.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest1.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest1.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest2.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest2.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest2.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest2.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest2.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest3.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest3.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest3.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest3.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest3.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest4.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest4.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest4.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest4.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest4.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest5.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest5.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest5.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest5.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest5.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest6.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest6.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest6.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatTest6.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatTest6.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatUmlauts.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatUmlauts.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatUmlauts.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibExportFormatUmlauts.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibExportFormatUmlauts.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibLCID.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibLCID.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibLCID.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibLCID.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibLCID.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibLCID.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibLCID.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibLCID.xml diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.bib b/src/test/resources/net/sf/jabref/logic/exporter/MsBibShorttitle.bib similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.bib rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibShorttitle.bib diff --git a/src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.xml b/src/test/resources/net/sf/jabref/logic/exporter/MsBibShorttitle.xml similarity index 100% rename from src/test/resources/net/sf/jabref/exporter/MsBibShorttitle.xml rename to src/test/resources/net/sf/jabref/logic/exporter/MsBibShorttitle.xml From fd7a61a8d41b9c7a3fb078ef91cf3aaaa729dfcc Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sat, 16 Jul 2016 17:16:43 +0200 Subject: [PATCH 241/268] Rename helpfile enum to singular Based on http://stackoverflow.com/questions/1335959/singular-or-plural-for-enumerations and http://stackoverflow.com/questions/15755955/naming-of-enums-in-java-singular-or-plural enums should be in singular form --- .../net/sf/jabref/gui/ContentSelectorDialog2.java | 4 ++-- .../net/sf/jabref/gui/GenFieldsCustomizer.java | 6 +++--- .../net/sf/jabref/gui/ImportInspectionDialog.java | 4 ++-- src/main/java/net/sf/jabref/gui/JabRefFrame.java | 4 ++-- src/main/java/net/sf/jabref/gui/StringDialog.java | 4 ++-- .../net/sf/jabref/gui/entryeditor/EntryEditor.java | 4 ++-- .../gui/exporter/ExportCustomizationDialog.java | 4 ++-- .../net/sf/jabref/gui/groups/GroupSelector.java | 4 ++-- .../java/net/sf/jabref/gui/help/HelpAction.java | 14 +++++++------- .../gui/help/{HelpFiles.java => HelpFile.java} | 4 ++-- .../jabref/gui/journals/ManageJournalsPanel.java | 4 ++-- .../jabref/gui/labelpattern/LabelPatternPanel.java | 4 ++-- .../sf/jabref/gui/openoffice/OpenOfficePanel.java | 4 ++-- .../net/sf/jabref/gui/preftabs/AdvancedTab.java | 4 ++-- .../java/net/sf/jabref/gui/preftabs/FileTab.java | 6 +++--- .../net/sf/jabref/gui/preftabs/GeneralTab.java | 6 +++--- .../sf/jabref/gui/preftabs/NameFormatterTab.java | 4 ++-- .../sf/jabref/gui/preftabs/TableColumnsTab.java | 4 ++-- .../java/net/sf/jabref/gui/search/SearchBar.java | 4 ++-- .../jabref/importer/ImportCustomizationDialog.java | 4 ++-- .../jabref/importer/fetcher/ACMPortalFetcher.java | 6 +++--- .../net/sf/jabref/importer/fetcher/ADSFetcher.java | 6 +++--- .../jabref/importer/fetcher/CiteSeerXFetcher.java | 6 +++--- .../sf/jabref/importer/fetcher/DBLPFetcher.java | 6 +++--- .../sf/jabref/importer/fetcher/DOAJFetcher.java | 6 +++--- .../importer/fetcher/DOItoBibTeXFetcher.java | 6 +++--- .../importer/fetcher/DiVAtoBibTeXFetcher.java | 6 +++--- .../sf/jabref/importer/fetcher/EntryFetcher.java | 6 +++--- .../net/sf/jabref/importer/fetcher/GVKFetcher.java | 6 +++--- .../importer/fetcher/GoogleScholarFetcher.java | 6 +++--- .../jabref/importer/fetcher/IEEEXploreFetcher.java | 6 +++--- .../sf/jabref/importer/fetcher/INSPIREFetcher.java | 6 +++--- .../importer/fetcher/ISBNtoBibTeXFetcher.java | 6 +++--- .../sf/jabref/importer/fetcher/MedlineFetcher.java | 6 +++--- .../sf/jabref/importer/fetcher/OAI2Fetcher.java | 6 +++--- .../importer/fetcher/ScienceDirectFetcher.java | 6 +++--- .../jabref/importer/fetcher/SpringerFetcher.java | 6 +++--- .../help/{HelpFilesTest.java => HelpFileTest.java} | 4 ++-- 38 files changed, 101 insertions(+), 101 deletions(-) rename src/main/java/net/sf/jabref/gui/help/{HelpFiles.java => HelpFile.java} (98%) rename src/test/java/net/sf/jabref/gui/help/{HelpFilesTest.java => HelpFileTest.java} (87%) diff --git a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java index e5274029ab6e..8dcf101b1c02 100644 --- a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java +++ b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java @@ -44,7 +44,7 @@ import net.sf.jabref.MetaData; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinder; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.logic.l10n.Localization; @@ -442,7 +442,7 @@ private void initLayout() { bsb.addButton(apply); bsb.addButton(cancel); bsb.addRelatedGap(); - bsb.addButton(new HelpAction(HelpFiles.CONTENT_SELECTOR).getHelpButton()); + bsb.addButton(new HelpAction(HelpFile.CONTENT_SELECTOR).getHelpButton()); bsb.addGlue(); // Add panels to dialog: diff --git a/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java b/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java index a77f161ffbef..8dea8268671b 100644 --- a/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java +++ b/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java @@ -39,7 +39,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; @@ -67,7 +67,7 @@ public class GenFieldsCustomizer extends JDialog { public GenFieldsCustomizer(JabRefFrame frame) { super(frame, Localization.lang("Set general fields"), false); parentFrame = frame; - helpBut = new HelpAction(HelpFiles.GENERAL_FIELDS).getHelpButton(); + helpBut = new HelpAction(HelpFile.GENERAL_FIELDS).getHelpButton(); jbInit(); setSize(new Dimension(650, 300)); } @@ -189,4 +189,4 @@ private void revertActionPerformed() { fieldsArea.setText(sb.toString()); } -} \ No newline at end of file +} diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 97d082028a50..712cd92e3686 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -77,7 +77,7 @@ import net.sf.jabref.gui.groups.GroupTreeNodeViewModel; import net.sf.jabref.gui.groups.UndoableChangeEntriesOfGroup; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.renderer.GeneralRenderer; import net.sf.jabref.gui.undo.NamedCompound; @@ -262,7 +262,7 @@ public ImportInspectionDialog(JabRefFrame frame, BasePanel panel, String undoNam JButton cancel = new JButton(Localization.lang("Cancel")); bb.addButton(cancel); bb.addRelatedGap(); - JButton help = new HelpAction(HelpFiles.IMPORT_INSPECTION).getHelpButton(); + JButton help = new HelpAction(HelpFile.IMPORT_INSPECTION).getHelpButton(); bb.addButton(help); bb.addGlue(); bb.getPanel().setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 4645e65ddcf3..5613c04e2409 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -101,7 +101,7 @@ import net.sf.jabref.gui.help.AboutAction; import net.sf.jabref.gui.help.AboutDialog; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.journals.ManageJournalsAction; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.keyboard.KeyBindingRepository; @@ -220,7 +220,7 @@ public class JabRefFrame extends JFrame implements OutputPrinter { private final AbstractAction openForumAction = new OpenBrowserAction("http://discourse.jabref.org/", Localization.menuTitle("Online help forum"), Localization.lang("Online help forum"), IconTheme.JabRefIcon.FORUM.getSmallIcon(), IconTheme.JabRefIcon.FORUM.getIcon()); private final AbstractAction help = new HelpAction(Localization.menuTitle("Online help"), Localization.lang("Online help"), - HelpFiles.CONTENTS, Globals.getKeyPrefs().getKey(KeyBinding.HELP)); + HelpFile.CONTENTS, Globals.getKeyPrefs().getKey(KeyBinding.HELP)); private final AbstractAction about = new AboutAction(Localization.menuTitle("About JabRef"), aboutDiag, Localization.lang("About JabRef"), IconTheme.getImage("about")); private final AbstractAction editEntry = new GeneralAction(Actions.EDIT, Localization.menuTitle("Edit entry"), diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index 57d642e5eeef..10b622d23d42 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -49,7 +49,7 @@ import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.undo.UndoableInsertString; import net.sf.jabref.gui.undo.UndoableRemoveString; @@ -88,7 +88,7 @@ public StringDialog(JabRefFrame frame, BasePanel panel, BibDatabase base) { sortStrings(); - helpAction = new HelpAction(Localization.lang("Help"), HelpFiles.STRING_EDITOR); + helpAction = new HelpAction(Localization.lang("Help"), HelpFile.STRING_EDITOR); addWindowListener(new WindowAdapter() { diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 0563224e6e9e..7e41bfa70c75 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -81,7 +81,7 @@ import net.sf.jabref.gui.fieldeditors.JTextAreaWithHighlighting; import net.sf.jabref.gui.fieldeditors.TextField; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.menus.ChangeEntryTypeMenu; import net.sf.jabref.gui.undo.NamedCompound; @@ -214,7 +214,7 @@ public EntryEditor(JabRefFrame frame, BasePanel panel, BibEntry entry) { displayedBibEntryType = entry.getType(); - helpAction = new HelpAction(HelpFiles.ENTRY_EDITOR, IconTheme.JabRefIcon.HELP.getIcon()); + helpAction = new HelpAction(HelpFile.ENTRY_EDITOR, IconTheme.JabRefIcon.HELP.getIcon()); closeAction = new CloseAction(); generateKeyAction = new GenerateKeyAction(); storeFieldAction = new StoreFieldAction(); diff --git a/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java index 38ba30fbe58b..d2c8bae31b60 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java @@ -40,7 +40,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.logic.l10n.Localization; @@ -141,7 +141,7 @@ public void actionPerformed(ActionEvent e) { JButton close = new JButton(Localization.lang("Close")); close.addActionListener(closeAction); - JButton help = new HelpAction(HelpFiles.CUSTOM_EXPORTS).getHelpButton(); + JButton help = new HelpAction(HelpFile.CUSTOM_EXPORTS).getHelpButton(); // Key bindings: JPanel main = new JPanel(); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 6a51d3b00af0..c4791b575f55 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -66,7 +66,7 @@ import net.sf.jabref.gui.SidePaneComponent; import net.sf.jabref.gui.SidePaneManager; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.maintable.MainTableDataModel; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.worker.AbstractWorker; @@ -242,7 +242,7 @@ public void stateChanged(ChangeEvent e) { newButton.setPreferredSize(butDim); newButton.setMinimumSize(butDim); - JButton helpButton = new HelpAction(Localization.lang("Help on groups"), HelpFiles.GROUP) + JButton helpButton = new HelpAction(Localization.lang("Help on groups"), HelpFile.GROUP) .getHelpButton(); helpButton.setPreferredSize(butDim); helpButton.setMinimumSize(butDim); diff --git a/src/main/java/net/sf/jabref/gui/help/HelpAction.java b/src/main/java/net/sf/jabref/gui/help/HelpAction.java index 83e10c2e3b73..20c50cdb9863 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpAction.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpAction.java @@ -40,30 +40,30 @@ public class HelpAction extends MnemonicAwareAction { private static final Log LOGGER = LogFactory.getLog(HelpAction.class); - private HelpFiles helpPage; + private HelpFile helpPage; - public HelpAction(String title, String tooltip, HelpFiles helpPage, KeyStroke key) { + public HelpAction(String title, String tooltip, HelpFile helpPage, KeyStroke key) { this(title, tooltip, helpPage, IconTheme.JabRefIcon.HELP.getSmallIcon()); putValue(Action.ACCELERATOR_KEY, key); } - private HelpAction(String title, String tooltip, HelpFiles helpPage, Icon icon) { + private HelpAction(String title, String tooltip, HelpFile helpPage, Icon icon) { super(icon); this.helpPage = helpPage; putValue(Action.NAME, title); putValue(Action.SHORT_DESCRIPTION, tooltip); } - public HelpAction(String tooltip, HelpFiles helpPage) { + public HelpAction(String tooltip, HelpFile helpPage) { this(Localization.lang("Help"), tooltip, helpPage, IconTheme.JabRefIcon.HELP.getSmallIcon()); } - public HelpAction(HelpFiles helpPage, Icon icon) { + public HelpAction(HelpFile helpPage, Icon icon) { this(Localization.lang("Help"), Localization.lang("Help"), helpPage, icon); } - public HelpAction(HelpFiles helpPage) { + public HelpAction(HelpFile helpPage) { this(Localization.lang("Help"), Localization.lang("Help"), helpPage, IconTheme.JabRefIcon.HELP.getSmallIcon()); } @@ -75,7 +75,7 @@ public JButton getHelpButton() { return button; } - public void setHelpFile(HelpFiles urlPart) { + public void setHelpFile(HelpFile urlPart) { this.helpPage = urlPart; } diff --git a/src/main/java/net/sf/jabref/gui/help/HelpFiles.java b/src/main/java/net/sf/jabref/gui/help/HelpFile.java similarity index 98% rename from src/main/java/net/sf/jabref/gui/help/HelpFiles.java rename to src/main/java/net/sf/jabref/gui/help/HelpFile.java index cda5ea2686f5..b3a252f4e554 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpFiles.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpFile.java @@ -20,7 +20,7 @@ * * @see help.jabref.org@github */ -public enum HelpFiles { +public enum HelpFile { COMMAND_LINE(""), //Empty because it refers to the TOC/index CONTENTS(""), @@ -70,7 +70,7 @@ public enum HelpFiles { * * @param pageName the URL path part of the help page */ - HelpFiles(String pageName) { + HelpFile(String pageName) { this.pageName = pageName; } diff --git a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java index 110b6c60bd83..d44b17311251 100644 --- a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java +++ b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java @@ -62,7 +62,7 @@ import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.net.MonitoredURLDownload; import net.sf.jabref.logic.journals.Abbreviation; @@ -166,7 +166,7 @@ public ManageJournalsPanel(final JabRefFrame frame) { bb.addButton(cancel); bb.addUnrelatedGap(); - JButton help = new HelpAction(HelpFiles.JOURNAL_ABBREV).getHelpButton(); + JButton help = new HelpAction(HelpFile.JOURNAL_ABBREV).getHelpButton(); bb.addButton(help); bb.addGlue(); bb.getPanel().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java index 9d97458fe43c..80943e74f9d0 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java @@ -36,7 +36,7 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.AbstractLabelPattern; import net.sf.jabref.logic.labelpattern.DatabaseLabelPattern; @@ -63,7 +63,7 @@ public class LabelPatternPanel extends JPanel { public LabelPatternPanel(BasePanel panel) { this.panel = panel; - help = new HelpAction(Localization.lang("Help on key patterns"), HelpFiles.LABEL_PATTERN); + help = new HelpAction(Localization.lang("Help on key patterns"), HelpFile.LABEL_PATTERN); buildGUI(); } diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java index 73d43b363cf9..c1d084a56816 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java @@ -53,7 +53,7 @@ import net.sf.jabref.gui.SidePaneManager; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.worker.AbstractWorker; import net.sf.jabref.logic.l10n.Localization; @@ -98,7 +98,7 @@ public class OpenOfficePanel extends AbstractWorker { private final JButton manageCitations = new JButton(Localization.lang("Manage citations")); private final JButton settingsB = new JButton(Localization.lang("Settings")); private final JButton help = new HelpAction(Localization.lang("OpenOffice/LibreOffice integration"), - HelpFiles.OPENOFFICE_LIBREOFFICE).getHelpButton(); + HelpFile.OPENOFFICE_LIBREOFFICE).getHelpButton(); private OOBibBase ooBase; private JabRefFrame frame; private SidePaneManager manager; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java index d49d25b2f4fb..1681cfdf8f19 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java @@ -28,7 +28,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.remote.JabRefMessageHandler; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.remote.RemotePreferences; @@ -82,7 +82,7 @@ public AdvancedTab(JabRefPreferences prefs) { JPanel p = new JPanel(); p.add(useRemoteServer); p.add(remoteServerPort); - p.add(new HelpAction(HelpFiles.REMOTE).getHelpButton()); + p.add(new HelpAction(HelpFile.REMOTE).getHelpButton()); builder.append(p); // IEEE diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index b4741a96e776..8ba24b05a2b7 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -36,7 +36,7 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import com.jgoodies.forms.builder.DefaultFormBuilder; @@ -167,7 +167,7 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { builder.append(regExpTextField); builder.append(new HelpAction(Localization.lang("Help on Regular Expression Search"), - HelpFiles.REGEX_SEARCH) + HelpFile.REGEX_SEARCH) .getHelpButton()); builder.nextLine(); builder.append(runAutoFileSearch, 3); @@ -177,7 +177,7 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { builder.appendSeparator(Localization.lang("Autosave")); builder.append(autoSave, 1); - JButton help = new HelpAction(HelpFiles.AUTOSAVE).getHelpButton(); + JButton help = new HelpAction(HelpFile.AUTOSAVE).getHelpButton(); help.setPreferredSize(new Dimension(24, 24)); JPanel hPan = new JPanel(); hPan.setLayout(new BorderLayout()); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java b/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java index 74206df40055..de24015ad887 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java @@ -35,7 +35,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseMode; @@ -144,7 +144,7 @@ public GeneralTab(JabRefPreferences prefs) { builder.append(overwriteOwner); builder.append(new JPanel(), 3); - JButton help = new HelpAction(HelpFiles.OWNER).getHelpButton(); + JButton help = new HelpAction(HelpFile.OWNER).getHelpButton(); builder.append(help); builder.nextLine(); @@ -154,7 +154,7 @@ public GeneralTab(JabRefPreferences prefs) { builder.append(Localization.lang("Field name") + ':'); builder.append(timeStampField); - help = new HelpAction(HelpFiles.TIMESTAMP).getHelpButton(); + help = new HelpAction(HelpFile.TIMESTAMP).getHelpButton(); builder.append(help); builder.nextLine(); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java b/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java index 794aecb07dda..5359d5da8c1e 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java @@ -39,7 +39,7 @@ import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.OSXCompatibleToolbar; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.format.NameFormatter; @@ -194,7 +194,7 @@ public void setValueAt(Object value, int row, int col) { toolBar.add(new AddRowAction()); toolBar.add(new DeleteRowAction()); toolBar.add(new HelpAction(Localization.lang("Help on Name Formatting"), - HelpFiles.CUSTOM_EXPORTS_NAME_FORMATTER).getHelpButton()); + HelpFile.CUSTOM_EXPORTS_NAME_FORMATTER).getHelpButton()); tabPanel.add(toolBar, BorderLayout.EAST); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java index a3aa069596ab..444beb55b0dd 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java @@ -53,7 +53,7 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.OSXCompatibleToolbar; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibtexSingleField; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -305,7 +305,7 @@ public void setValueAt(Object value, int row, int col) { /*** begin: special table columns and special fields ***/ JButton helpButton = new HelpAction(Localization.lang("Help on special fields"), - HelpFiles.SPECIAL_FIELDS).getHelpButton(); + HelpFile.SPECIAL_FIELDS).getHelpButton(); rankingColumn = new JCheckBox(Localization.lang("Show rank")); qualityColumn = new JCheckBox(Localization.lang("Show quality")); diff --git a/src/main/java/net/sf/jabref/gui/search/SearchBar.java b/src/main/java/net/sf/jabref/gui/search/SearchBar.java index 6492b8507ef0..f5d3aceaf9f8 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchBar.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchBar.java @@ -40,7 +40,7 @@ import net.sf.jabref.gui.WrapLayout; import net.sf.jabref.gui.autocompleter.AutoCompleteSupport; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.maintable.MainTableDataModel; import net.sf.jabref.gui.util.component.JTextFieldWithUnfocusedText; import net.sf.jabref.gui.worker.AbstractWorker; @@ -172,7 +172,7 @@ public SearchBar(BasePanel basePanel) { globalSearch.setEnabled(false); toolBar.add(globalSearch); toolBar.addSeparator(); - toolBar.add(new HelpAction(HelpFiles.SEARCH)); + toolBar.add(new HelpAction(HelpFile.SEARCH)); this.add(toolBar); this.add(currentResults); diff --git a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java index 02430db7513a..a18e6c6d244b 100644 --- a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java @@ -48,7 +48,7 @@ import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.importer.fileformat.ImportFormat; @@ -197,7 +197,7 @@ public void actionPerformed(ActionEvent e) { JButton closeButton = new JButton(Localization.lang("Close")); closeButton.addActionListener(closeAction); - JButton helpButton = new HelpAction(HelpFiles.CUSTOM_IMPORTS).getHelpButton(); + JButton helpButton = new HelpAction(HelpFile.CUSTOM_IMPORTS).getHelpButton(); // Key bindings: diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java index f4851c052709..ab9b322df61e 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java @@ -44,7 +44,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FetcherPreviewDialog; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -414,8 +414,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_ACM; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_ACM; } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java index d15d3e9f638c..54695aaf0143 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java @@ -39,7 +39,7 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; @@ -70,8 +70,8 @@ public JPanel getOptionsPanel() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_ADS; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_ADS; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java index e27f32e7336d..0b6a3f0a2e3b 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java @@ -25,7 +25,7 @@ import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter; @@ -87,8 +87,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_CITESEERX; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_CITESEERX; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java index b1853e6c85be..119e5d8a7812 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java @@ -24,7 +24,7 @@ import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -162,8 +162,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_DBLP; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_DBLP; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java index ebcdb3ad6ef5..ca5ec8b44d55 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java @@ -18,7 +18,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.JSONEntryParser; @@ -125,8 +125,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_DOAJ; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_DOAJ; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index 5ad05a0eb65b..fdd66cdf9572 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -11,7 +11,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; @@ -55,8 +55,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_DOI_TO_BIBTEX; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_DOI_TO_BIBTEX; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java index 9e58b2a8ebb7..9dfb60eadff5 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java @@ -27,7 +27,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -125,8 +125,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_DIVA_TO_BIBTEX; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_DIVA_TO_BIBTEX; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java index 8aa60e2ac745..709e750c7eff 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java @@ -18,7 +18,7 @@ import javax.swing.JPanel; import net.sf.jabref.gui.ImportInspectionDialog; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -68,9 +68,9 @@ public interface EntryFetcher extends ImportInspectionDialog.CallBack { * If given, a question mark is displayed in the side pane which leads to * the help page. * - * @return The {@link HelpFiles} enum constant for the help page + * @return The {@link HelpFile} enum constant for the help page */ - HelpFiles getHelpPage(); + HelpFile getHelpPage(); /** * If this activeFetcher requires additional options, a panel for setting up these diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java index bddcd9651e1c..4e900d3719e9 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java @@ -19,7 +19,7 @@ import javax.swing.JPanel; import javax.xml.parsers.ParserConfigurationException; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.logic.l10n.Localization; @@ -62,8 +62,8 @@ public void stopFetching() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_GVK; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_GVK; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java index 20779a5618cf..e546ec37598d 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java @@ -33,7 +33,7 @@ import javax.swing.JPanel; import net.sf.jabref.gui.FetcherPreviewDialog; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; @@ -149,8 +149,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_GOOGLE_SCHOLAR; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_GOOGLE_SCHOLAR; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index 2ff15326bd6d..ff1f21963d34 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -37,7 +37,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -198,8 +198,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_IEEEXPLORE; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_IEEEXPLORE; } /** diff --git a/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java index 16e027378304..46cd6f3664a2 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java @@ -28,7 +28,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; @@ -139,8 +139,8 @@ private BibDatabase importInspireEntries(String key, OutputPrinter frame) { * @see net.sf.jabref.imports.fetcher.EntryFetcher */ @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_INSPIRE; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_INSPIRE; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java index 92e7388edb01..c926add43a32 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java @@ -28,7 +28,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -134,8 +134,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_ISBN_TO_BIBTEX; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_ISBN_TO_BIBTEX; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java index 586870b691aa..163775150641 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java @@ -29,7 +29,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; @@ -128,8 +128,8 @@ public void stopFetching() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_MEDLINE; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_MEDLINE; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java index d8f25b997c02..e59f19a5ba12 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java @@ -31,7 +31,7 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OAI2Handler; import net.sf.jabref.importer.OutputPrinter; @@ -233,8 +233,8 @@ public BibEntry importOai2Entry(String key) { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_OAI2_ARXIV; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_OAI2_ARXIV; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java index 9dfdd98fda29..54478da27344 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java @@ -26,7 +26,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFiles; +import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.logic.l10n.Localization; @@ -59,8 +59,8 @@ public class ScienceDirectFetcher implements EntryFetcher { @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_SCIENCEDIRECT; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_SCIENCEDIRECT; } @Override diff --git a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java index b74ebafc0506..2b23c1f24683 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java @@ -19,7 +19,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; - import net.sf.jabref.gui.help.HelpFiles; + import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.JSONEntryParser; @@ -130,8 +130,8 @@ public String getTitle() { } @Override - public HelpFiles getHelpPage() { - return HelpFiles.FETCHER_SPRINGER; + public HelpFile getHelpPage() { + return HelpFile.FETCHER_SPRINGER; } @Override diff --git a/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java b/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java similarity index 87% rename from src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java rename to src/test/java/net/sf/jabref/gui/help/HelpFileTest.java index 0dc0d2983953..62f4beda4c1f 100644 --- a/src/test/java/net/sf/jabref/gui/help/HelpFilesTest.java +++ b/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java @@ -8,11 +8,11 @@ import static junit.framework.TestCase.assertEquals; -public class HelpFilesTest { +public class HelpFileTest { private final String jabrefHelp = "http://help.jabref.org/en/"; @Test public void referToValidPage() throws IOException { - for (HelpFiles help : HelpFiles.values()) { + for (HelpFile help : HelpFile.values()) { URL url = new URL(jabrefHelp + help.getPageName()); HttpURLConnection http = (HttpURLConnection) url.openConnection(); assertEquals(200, http.getResponseCode()); From 01493185103cc3244676e676906421964cce0110 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sun, 17 Jul 2016 16:49:18 +0200 Subject: [PATCH 242/268] Fixed #1592 --- CHANGELOG.md | 1 + src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 292f3c65486c..190b322dfc96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly - LaTeX to Unicode converter now handles combining accents - Fixed [#1527](https://github.com/JabRef/jabref/issues/1527): 'Get BibTeX data from DOI' Removes Marking +- Fixed [#1592](https://github.com/JabRef/jabref/issues/1592): LibreOffice: wrong numbers in citation labels ### Removed diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java index fc0c8a52ef36..019a4a54cbad 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java @@ -523,7 +523,7 @@ private List refreshCiteMarkersInternal(List databases, OOB } else { num.add(j, lastNum + 1); if (numbers.containsKey(keys[j])) { - num.add(j, numbers.get(keys[j])); + num.set(j, numbers.get(keys[j])); } else { numbers.put(keys[j], num.get(j)); lastNum = num.get(j); From 71a982e370f6b8912b71df83653b4ef8e808296a Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Mon, 18 Jul 2016 13:22:48 +0200 Subject: [PATCH 243/268] Remove error prone plugin as it does not work anymore on windows. --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cfdea1659bbe..9dcb2c663b41 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,8 @@ plugins { id 'com.github.johnrengelman.shadow' version '1.2.3' // TODO replaced by spotless plugin, needs to be updated id "com.github.youribonnaffe.gradle.format" version "1.5" - id "net.ltgt.errorprone" version "0.0.8" + //Removed for now as it does not work anymore on windows + //id "net.ltgt.errorprone" version "0.0.8" id 'me.champeau.gradle.jmh' version '0.3.0' } From 242da91c0e6d9ac510a4b44bc69d243bd5269d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lenhard?= Date: Mon, 18 Jul 2016 15:05:02 +0200 Subject: [PATCH 244/268] Move event (#1601) * Move event package to model --- src/main/java/net/sf/jabref/gui/BasePanel.java | 4 ++-- src/main/java/net/sf/jabref/gui/PreviewPanel.java | 2 +- .../java/net/sf/jabref/gui/entryeditor/EntryEditor.java | 2 +- .../net/sf/jabref/gui/maintable/ListSynchronizer.java | 6 +++--- .../java/net/sf/jabref/model/database/BibDatabase.java | 8 ++++---- src/main/java/net/sf/jabref/model/entry/BibEntry.java | 2 +- .../net/sf/jabref/{ => model}/event/EntryAddedEvent.java | 2 +- .../sf/jabref/{ => model}/event/EntryChangedEvent.java | 2 +- .../java/net/sf/jabref/{ => model}/event/EntryEvent.java | 2 +- .../sf/jabref/{ => model}/event/EntryRemovedEvent.java | 2 +- .../sf/jabref/{ => model}/event/FieldChangedEvent.java | 2 +- .../specialfields/SpecialFieldDatabaseChangeListener.java | 2 +- .../jabref/specialfields/SpecialFieldUpdateListener.java | 2 +- .../net/sf/jabref/model/database/BibDatabaseTest.java | 2 +- .../sf/jabref/{ => model}/event/TestEventListener.java | 2 +- 15 files changed, 21 insertions(+), 21 deletions(-) rename src/main/java/net/sf/jabref/{ => model}/event/EntryAddedEvent.java (97%) rename src/main/java/net/sf/jabref/{ => model}/event/EntryChangedEvent.java (91%) rename src/main/java/net/sf/jabref/{ => model}/event/EntryEvent.java (93%) rename src/main/java/net/sf/jabref/{ => model}/event/EntryRemovedEvent.java (91%) rename src/main/java/net/sf/jabref/{ => model}/event/FieldChangedEvent.java (96%) rename src/test/java/net/sf/jabref/{ => model}/event/TestEventListener.java (94%) diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 8e65a47c2b72..0765ed943b29 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -61,8 +61,6 @@ import net.sf.jabref.collab.ChangeScanner; import net.sf.jabref.collab.FileUpdateListener; import net.sf.jabref.collab.FileUpdatePanel; -import net.sf.jabref.event.EntryAddedEvent; -import net.sf.jabref.event.EntryChangedEvent; import net.sf.jabref.external.AttachFileAction; import net.sf.jabref.external.ExternalFileMenuItem; import net.sf.jabref.external.ExternalFileType; @@ -131,6 +129,8 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.model.event.EntryAddedEvent; +import net.sf.jabref.model.event.EntryChangedEvent; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index a5e326a58158..e697755a020e 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -50,7 +50,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.fieldeditors.PreviewPanelTransferHandler; import net.sf.jabref.gui.keyboard.KeyBinding; @@ -60,6 +59,7 @@ import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.search.SearchQueryHighlightListener; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.event.FieldChangedEvent; import com.google.common.eventbus.Subscribe; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 7e41bfa70c75..46f51444f44b 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -65,7 +65,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.external.WriteXMPEntryEditorAction; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryContainer; @@ -110,6 +109,7 @@ import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.model.event.FieldChangedEvent; import net.sf.jabref.specialfields.SpecialFieldUpdateListener; import com.google.common.eventbus.Subscribe; diff --git a/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java b/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java index 1915cfe2cd2d..ac718335ca22 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java +++ b/src/main/java/net/sf/jabref/gui/maintable/ListSynchronizer.java @@ -15,10 +15,10 @@ */ package net.sf.jabref.gui.maintable; -import net.sf.jabref.event.EntryAddedEvent; -import net.sf.jabref.event.EntryChangedEvent; -import net.sf.jabref.event.EntryRemovedEvent; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.event.EntryAddedEvent; +import net.sf.jabref.model.event.EntryChangedEvent; +import net.sf.jabref.model.event.EntryRemovedEvent; import ca.odell.glazedlists.EventList; import com.google.common.eventbus.Subscribe; diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index 18e6afed685a..20905246f84f 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -43,15 +43,15 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; -import net.sf.jabref.event.EntryAddedEvent; -import net.sf.jabref.event.EntryChangedEvent; -import net.sf.jabref.event.EntryRemovedEvent; -import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.EntryUtil; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; +import net.sf.jabref.model.event.EntryAddedEvent; +import net.sf.jabref.model.event.EntryChangedEvent; +import net.sf.jabref.model.event.EntryRemovedEvent; +import net.sf.jabref.model.event.FieldChangedEvent; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index f4c5a86c84ed..409ee00e7cca 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -36,9 +36,9 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.event.FieldChangedEvent; import com.google.common.base.Strings; import com.google.common.eventbus.EventBus; diff --git a/src/main/java/net/sf/jabref/event/EntryAddedEvent.java b/src/main/java/net/sf/jabref/model/event/EntryAddedEvent.java similarity index 97% rename from src/main/java/net/sf/jabref/event/EntryAddedEvent.java rename to src/main/java/net/sf/jabref/model/event/EntryAddedEvent.java index 82682d17d319..4332e37c4d4b 100644 --- a/src/main/java/net/sf/jabref/event/EntryAddedEvent.java +++ b/src/main/java/net/sf/jabref/model/event/EntryAddedEvent.java @@ -13,7 +13,7 @@ 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.event; +package net.sf.jabref.model.event; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/event/EntryChangedEvent.java b/src/main/java/net/sf/jabref/model/event/EntryChangedEvent.java similarity index 91% rename from src/main/java/net/sf/jabref/event/EntryChangedEvent.java rename to src/main/java/net/sf/jabref/model/event/EntryChangedEvent.java index eb1e8ada15af..62e82760d1c6 100644 --- a/src/main/java/net/sf/jabref/event/EntryChangedEvent.java +++ b/src/main/java/net/sf/jabref/model/event/EntryChangedEvent.java @@ -1,4 +1,4 @@ -package net.sf.jabref.event; +package net.sf.jabref.model.event; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/event/EntryEvent.java b/src/main/java/net/sf/jabref/model/event/EntryEvent.java similarity index 93% rename from src/main/java/net/sf/jabref/event/EntryEvent.java rename to src/main/java/net/sf/jabref/model/event/EntryEvent.java index 8770ab940f59..e82959014dd1 100644 --- a/src/main/java/net/sf/jabref/event/EntryEvent.java +++ b/src/main/java/net/sf/jabref/model/event/EntryEvent.java @@ -1,4 +1,4 @@ -package net.sf.jabref.event; +package net.sf.jabref.model.event; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/event/EntryRemovedEvent.java b/src/main/java/net/sf/jabref/model/event/EntryRemovedEvent.java similarity index 91% rename from src/main/java/net/sf/jabref/event/EntryRemovedEvent.java rename to src/main/java/net/sf/jabref/model/event/EntryRemovedEvent.java index 888f8fd24676..ec6a375557a2 100644 --- a/src/main/java/net/sf/jabref/event/EntryRemovedEvent.java +++ b/src/main/java/net/sf/jabref/model/event/EntryRemovedEvent.java @@ -1,4 +1,4 @@ -package net.sf.jabref.event; +package net.sf.jabref.model.event; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/event/FieldChangedEvent.java b/src/main/java/net/sf/jabref/model/event/FieldChangedEvent.java similarity index 96% rename from src/main/java/net/sf/jabref/event/FieldChangedEvent.java rename to src/main/java/net/sf/jabref/model/event/FieldChangedEvent.java index 3ae28e8f7ba7..f634d77a33dd 100644 --- a/src/main/java/net/sf/jabref/event/FieldChangedEvent.java +++ b/src/main/java/net/sf/jabref/model/event/FieldChangedEvent.java @@ -1,4 +1,4 @@ -package net.sf.jabref.event; +package net.sf.jabref.model.event; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java index 6ad1449b7387..b9f5ecdf597b 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldDatabaseChangeListener.java @@ -15,10 +15,10 @@ */ package net.sf.jabref.specialfields; -import net.sf.jabref.event.EntryAddedEvent; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.event.EntryAddedEvent; import com.google.common.eventbus.Subscribe; diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java index aa1eed50c411..b5174a5485dc 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java @@ -18,9 +18,9 @@ import javax.swing.SwingUtilities; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.event.FieldChangedEvent; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.event.FieldChangedEvent; import com.google.common.eventbus.Subscribe; diff --git a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java index 8106d11371f9..012cb5b8f3e9 100644 --- a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java +++ b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java @@ -8,12 +8,12 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.event.TestEventListener; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.model.event.TestEventListener; import org.junit.Before; import org.junit.Rule; diff --git a/src/test/java/net/sf/jabref/event/TestEventListener.java b/src/test/java/net/sf/jabref/model/event/TestEventListener.java similarity index 94% rename from src/test/java/net/sf/jabref/event/TestEventListener.java rename to src/test/java/net/sf/jabref/model/event/TestEventListener.java index 63a424dd80b2..68a9f68c62cf 100644 --- a/src/test/java/net/sf/jabref/event/TestEventListener.java +++ b/src/test/java/net/sf/jabref/model/event/TestEventListener.java @@ -1,4 +1,4 @@ -package net.sf.jabref.event; +package net.sf.jabref.model.event; import net.sf.jabref.model.entry.BibEntry; From c326573f28e67d94c823c8383ef1504774f0dc9e Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 18 Jul 2016 15:23:00 +0200 Subject: [PATCH 245/268] Update dependencies: postgres 9.4.1208 -> 9.4.1209 and wiremock from 2.1.6 to 2.1.7 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 9dcb2c663b41..1deb505368eb 100644 --- a/build.gradle +++ b/build.gradle @@ -95,7 +95,7 @@ dependencies { // VersionEye states that 6.0.3 is the most recent version, but http://dev.mysql.com/downloads/connector/j/ shows that as "Development Release" compile 'mysql:mysql-connector-java:5.1.39' - compile 'org.postgresql:postgresql:9.4.1208' + compile 'org.postgresql:postgresql:9.4.1209' compile 'net.java.dev.glazedlists:glazedlists_java15:1.9.1' compile fileTree(dir: 'lib', includes: ['*.jar']) @@ -116,7 +116,7 @@ dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' - testCompile 'com.github.tomakehurst:wiremock:2.1.6' + testCompile 'com.github.tomakehurst:wiremock:2.1.7' testCompile 'org.assertj:assertj-swing-junit:3.4.0' } From 6824574730f9d25cb716ac867965ebda4ee03eba Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Mon, 18 Jul 2016 16:02:32 +0200 Subject: [PATCH 246/268] Added ISBN integrity checker (#1586) * Added ISBN integrity checker * Extracted ISBN class --- CHANGELOG.md | 1 + .../jabref/logic/integrity/ISBNChecker.java | 37 +++++++++ .../logic/integrity/IntegrityCheck.java | 1 + .../java/net/sf/jabref/logic/util/ISBN.java | 76 +++++++++++++++++++ .../logic/integrity/IntegrityCheckTest.java | 11 ++- 5 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java create mode 100644 src/main/java/net/sf/jabref/logic/util/ISBN.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 190b322dfc96..de3444dab66b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - For developers: Moved the bst package into logic. This requires the regeneration of antlr sources, execute: gradlew generateSource - [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings - [#1249](https://github.com/JabRef/jabref/issues/1249) Date layout formatter added +- Added ISBN integrity checker ### Fixed - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java new file mode 100644 index 000000000000..0aaec654c109 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java @@ -0,0 +1,37 @@ +package net.sf.jabref.logic.integrity; + +import java.util.Collections; +import java.util.List; + +import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.ISBN; +import net.sf.jabref.model.entry.BibEntry; + + +public class ISBNChecker implements Checker { + + + @Override + public List check(BibEntry entry) { + if (!entry.hasField("isbn")) { + return Collections.emptyList(); + } + + // Check that the ISBN is on the correct form + ISBN isbn = new ISBN(entry.getFieldOptional("isbn").get()); + + if (!isbn.isValidFormat()) { + return Collections.singletonList( + new IntegrityMessage(Localization.lang("incorrect format"), entry, "isbn")); + } + + if (!isbn.isValidChecksum()) { + return Collections + .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, "isbn")); + } + + return Collections.emptyList(); + } + +} diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 1d45fddd36c2..90f5292941bf 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -68,6 +68,7 @@ private List checkBibtexEntry(BibEntry entry) { result.addAll(new HTMLCharacterChecker().check(entry)); result.addAll(new BooktitleChecker().check(entry)); result.addAll(new ISSNChecker().check(entry)); + result.addAll(new ISBNChecker().check(entry)); return result; } diff --git a/src/main/java/net/sf/jabref/logic/util/ISBN.java b/src/main/java/net/sf/jabref/logic/util/ISBN.java new file mode 100644 index 000000000000..b470bb51309e --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/util/ISBN.java @@ -0,0 +1,76 @@ +package net.sf.jabref.logic.util; + +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ISBN { + + private static final Pattern ISBN_PATTERN = Pattern.compile("^(\\d{9}[\\dxX]|\\d{13})$"); + + private final String isbnString; + + + public ISBN(String isbnString) { + this.isbnString = Objects.requireNonNull(isbnString).trim().replace("-", ""); + } + + public boolean isValidFormat() { + Matcher isbnMatcher = ISBN_PATTERN.matcher(isbnString); + if (isbnMatcher.matches()) { + return true; + } + return false; + } + + public boolean isValidChecksum() { + boolean valid; + if (isbnString.length() == 10) { + valid = isbn10check(); + } else { + // length is either 10 or 13 based on regexp so will be 13 here + valid = isbn13check(); + } + return valid; + } + + public boolean isIsbn10() { + return isbn10check(); + } + + public boolean isIsbn13() { + return isbn13check(); + } + + // Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Book_Number#Check_digits + private boolean isbn10check() { + if ((isbnString == null) || (isbnString.length() != 10)) { + return false; + } + + int sum = 0; + for (int pos = 0; pos <= 8; pos++) { + sum += (isbnString.charAt(pos) - '0') * ((10 - pos)); + } + char control = isbnString.charAt(9); + if ((control == 'x') || (control == 'X')) { + control = '9' + 1; + } + sum += (control - '0'); + return (sum % 11) == 0; + } + + // Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Book_Number#Check_digits + private boolean isbn13check() { + if ((isbnString == null) || (isbnString.length() != 13)) { + return false; + } + + int sum = 0; + for (int pos = 0; pos <= 12; pos++) { + sum += (isbnString.charAt(pos) - '0') * ((pos % 2) == 0 ? 1 : 3); + } + return (sum % 10) == 0; + } + +} diff --git a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java index b2242e6d9b8b..74de0c7c2a82 100644 --- a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java @@ -196,7 +196,6 @@ public void testHTMLCharacterChecks() { @Test public void testISSNChecks() { - assertCorrect(createContext("issn", "0020-7217")); assertCorrect(createContext("issn", "0020-7217")); assertCorrect(createContext("issn", "1687-6180")); assertCorrect(createContext("issn", "2434-561x")); @@ -204,6 +203,16 @@ public void testISSNChecks() { assertWrong(createContext("issn", "0020-7218")); } + @Test + public void testISBNChecks() { + assertCorrect(createContext("isbn", "0-201-53082-1")); + assertCorrect(createContext("isbn", "0-9752298-0-X")); + assertCorrect(createContext("isbn", "978-0-306-40615-7")); + assertWrong(createContext("isbn", "Some other stuff")); + assertWrong(createContext("isbn", "0-201-53082-2")); + assertWrong(createContext("isbn", "978-0-306-40615-8")); + } + private BibDatabaseContext createContext(String field, String value, String type) { BibEntry entry = new BibEntry(); entry.setField(field, value); From e1e90cb30e35d243d1e500860c499bc6d624bf9f Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 18 Jul 2016 17:18:50 +0200 Subject: [PATCH 247/268] Reenable errorprone (see http://errorprone.info/) --- build.gradle | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1deb505368eb..7bad1052dde2 100644 --- a/build.gradle +++ b/build.gradle @@ -16,11 +16,17 @@ plugins { id 'com.github.johnrengelman.shadow' version '1.2.3' // TODO replaced by spotless plugin, needs to be updated id "com.github.youribonnaffe.gradle.format" version "1.5" - //Removed for now as it does not work anymore on windows - //id "net.ltgt.errorprone" version "0.0.8" + // If this is updated to 0.0.9, check configurations.errorprone + id "net.ltgt.errorprone" version "0.0.8" id 'me.champeau.gradle.jmh' version '0.3.0' } +configurations.errorprone { + // 2.0.10 does not work on Windows while 2.0.9 does + // See https://github.com/google/error-prone/issues/432 + resolutionStrategy.force 'com.google.errorprone:error_prone_core:2.0.9' +} + apply plugin: "java" apply plugin: "application" apply plugin: "project-report" From aa4c035ae46d5499c6fd9534d5bdc58c1aeee7c5 Mon Sep 17 00:00:00 2001 From: Admir Obralija Date: Tue, 19 Jul 2016 10:24:22 +0200 Subject: [PATCH 248/268] Extend the OpenConsoleFeature (#1582) * Extend the OpenConsoleFeature by selection of custom terminal emulator. - Add radio selection to the AdvancedTab - Add new JabRefPreferences - Add file check and execution commands - Add localization keys * Fix localization key. * Move console selection to ExternalTab.java * Change localization entry. * Add command executor. * Fix placeholder replacement. * Fix codacy. * Update localization key. * Remove "Specify terminal emulator" option. Add GUI outputs. * Set default command for Windows. Fix localization entries. * Remove empty lines in language files. * Use lambda expressions insead of ActionListeners * Refactoring. * Update CHANGELOG.md. * Small refactorings. --- CHANGELOG.md | 1 + .../java/net/sf/jabref/JabRefPreferences.java | 10 +++ .../sf/jabref/gui/desktop/JabRefDesktop.java | 47 ++++++++++- .../sf/jabref/gui/preftabs/ExternalTab.java | 82 +++++++++++++++++++ src/main/resources/l10n/JabRef_da.properties | 7 ++ src/main/resources/l10n/JabRef_de.properties | 7 +- src/main/resources/l10n/JabRef_en.properties | 9 +- src/main/resources/l10n/JabRef_es.properties | 7 ++ src/main/resources/l10n/JabRef_fa.properties | 7 ++ src/main/resources/l10n/JabRef_fr.properties | 7 ++ src/main/resources/l10n/JabRef_in.properties | 7 ++ src/main/resources/l10n/JabRef_it.properties | 7 ++ src/main/resources/l10n/JabRef_ja.properties | 7 ++ src/main/resources/l10n/JabRef_nl.properties | 7 ++ src/main/resources/l10n/JabRef_no.properties | 7 ++ .../resources/l10n/JabRef_pt_BR.properties | 7 ++ src/main/resources/l10n/JabRef_ru.properties | 7 ++ src/main/resources/l10n/JabRef_sv.properties | 7 ++ src/main/resources/l10n/JabRef_tr.properties | 7 ++ src/main/resources/l10n/JabRef_vi.properties | 7 ++ src/main/resources/l10n/JabRef_zh.properties | 7 ++ 21 files changed, 258 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de3444dab66b..42d087aef5ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed +- [#462](https://github.com/JabRef/jabref/issues/462) Extend the OpenConsoleFeature by offering a selection between default terminal emulator and configurable command execution. - [#1516](https://github.com/JabRef/jabref/issues/1516) Selected field names are written in uppercase in the entry editor - For developers: Moved the bst package into logic. This requires the regeneration of antlr sources, execute: gradlew generateSource - [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index 79cae1b39fcf..648b81f5ab6d 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -278,6 +278,9 @@ public class JabRefPreferences { public static final String KEY_PATTERN_REGEX = "KeyPatternRegex"; public static final String KEY_PATTERN_REPLACEMENT = "KeyPatternReplacement"; + public static final String CONSOLE_COMMAND = "consoleCommand"; + public static final String USE_DEFAULT_CONSOLE_APPLICATION = "useDefaultConsoleApplication"; + // Currently, it is not possible to specify defaults for specific entry types // When this should be made possible, the code to inspect is net.sf.jabref.gui.preftabs.LabelPatternPrefTab.storeSettings() -> LabelPattern keypatterns = getLabelPattern(); etc public static final String DEFAULT_LABEL_PATTERN = "defaultLabelPattern"; @@ -864,6 +867,13 @@ private JabRefPreferences() { defaults.put(LINE_LENGTH, 65); defaults.put(INDENT, 4); + defaults.put(USE_DEFAULT_CONSOLE_APPLICATION, Boolean.TRUE); + if (OS.WINDOWS) { + defaults.put(CONSOLE_COMMAND, "C:\\Program Files\\ConEmu\\ConEmu64.exe /single /dir \"%DIR\""); + } else { + defaults.put(CONSOLE_COMMAND, ""); + } + //versioncheck defaults defaults.put(VersionPreferences.VERSION_IGNORED_UPDATE, ""); } diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index 0c48eaf3f1e8..f85695149a2f 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -28,6 +28,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; +import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypeEntryEditor; import net.sf.jabref.external.ExternalFileTypes; @@ -303,13 +304,57 @@ public static void openBrowserShowPopup(String url) { } } + /** + * Opens a new console starting on the given file location + * + * If no command is specified in {@link Globals}, + * the default system console will be executed. + * + * @param file Location the console should be opened at. + */ public static void openConsole(File file) throws IOException { if (file == null) { return; } String absolutePath = file.toPath().toAbsolutePath().getParent().toString(); - NATIVE_DESKTOP.openConsole(absolutePath); + boolean usingDefault = Globals.prefs.getBoolean(JabRefPreferences.USE_DEFAULT_CONSOLE_APPLICATION); + + if (usingDefault) { + NATIVE_DESKTOP.openConsole(absolutePath); + } else { + String command = Globals.prefs.get(JabRefPreferences.CONSOLE_COMMAND); + command = command.trim(); + + if (!command.isEmpty()) { + command = command.replaceAll("\\s+", " "); // normalize white spaces + String[] subcommands = command.split(" "); + StringBuilder commandLoggingText = new StringBuilder(); + + for (int i = 0; i < subcommands.length; i++) { + subcommands[i] = subcommands[i].replace("%DIR", absolutePath); // replace the placeholder if used + commandLoggingText.append(subcommands[i]); + if (i < (subcommands.length - 1)) { + commandLoggingText.append(" "); + } + } + + JabRefGUI.getMainFrame().output(Localization.lang("Executing command \"%0\"...", commandLoggingText.toString())); + LOGGER.info("Executing command \"" + commandLoggingText.toString() + "\"..."); + + try { + new ProcessBuilder(subcommands).start(); + } catch (IOException exception) { + LOGGER.error("Open console", exception); + + JOptionPane.showMessageDialog(JabRefGUI.getMainFrame(), + Localization.lang("Error_occured_while_executing_the_command_\"%0\".", commandLoggingText.toString()), + Localization.lang("Open console") + " - " + Localization.lang("Error"), + JOptionPane.ERROR_MESSAGE); + JabRefGUI.getMainFrame().output(null); + } + } + } } // TODO: Move to OS.java diff --git a/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java b/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java index 0683d2b10687..a33649df0e40 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java @@ -16,15 +16,22 @@ package net.sf.jabref.gui.preftabs; import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.awt.GridLayout; +import java.awt.Insets; import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; +import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JRadioButton; import javax.swing.JTextField; +import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileTypeEditor; import net.sf.jabref.external.push.PushToApplication; @@ -45,6 +52,12 @@ class ExternalTab extends JPanel implements PrefsTab { private final JTextField citeCommand; private final JCheckBox openFoldersOfAttachedFiles; + private final JRadioButton defaultConsole; + private final JRadioButton executeConsole; + private final JTextField consoleCommand; + private final JButton browseButton; + + public ExternalTab(JabRefFrame frame, PreferencesDialog prefsDiag, JabRefPreferences prefs) { this.prefs = prefs; this.frame = frame; @@ -54,6 +67,47 @@ public ExternalTab(JabRefFrame frame, PreferencesDialog prefsDiag, JabRefPrefere citeCommand = new JTextField(25); editFileTypes.addActionListener(ExternalFileTypeEditor.getAction(prefsDiag)); + + defaultConsole = new JRadioButton(Localization.lang("Use default terminal emulator")); + executeConsole = new JRadioButton(Localization.lang("Execute command") + ":"); + consoleCommand = new JTextField(); + browseButton = new JButton(Localization.lang("Browse")); + + JLabel commandDescription = new JLabel(Localization.lang( + "Note: Use the placeholder %0 for the location of the opened database file.", "%DIR")); + + ButtonGroup consoleOptions = new ButtonGroup(); + consoleOptions.add(defaultConsole); + consoleOptions.add(executeConsole); + + JPanel consoleOptionPanel = new JPanel(new GridBagLayout()); + GridBagConstraints layoutConstraints = new GridBagConstraints(); + + defaultConsole.addActionListener(e -> updateExecuteConsoleButtonAndFieldEnabledState()); + executeConsole.addActionListener(e -> updateExecuteConsoleButtonAndFieldEnabledState()); + browseButton.addActionListener(e -> showConsoleChooser()); + + layoutConstraints.fill = GridBagConstraints.HORIZONTAL; + + layoutConstraints.gridx = 0; + layoutConstraints.gridy = 0; + layoutConstraints.insets = new Insets(0, 0, 6, 0); + consoleOptionPanel.add(defaultConsole, layoutConstraints); + + layoutConstraints.gridy = 1; + consoleOptionPanel.add(executeConsole, layoutConstraints); + + layoutConstraints.gridx = 1; + consoleOptionPanel.add(consoleCommand, layoutConstraints); + + layoutConstraints.gridx = 2; + layoutConstraints.insets = new Insets(0, 4, 6, 0); + consoleOptionPanel.add(browseButton, layoutConstraints); + + layoutConstraints.gridx = 1; + layoutConstraints.gridy = 2; + consoleOptionPanel.add(commandDescription, layoutConstraints); + FormLayout layout = new FormLayout( "1dlu, 8dlu, left:pref, 4dlu, fill:150dlu, 4dlu, fill:pref", ""); @@ -92,6 +146,12 @@ public ExternalTab(JabRefFrame frame, PreferencesDialog prefsDiag, JabRefPrefere builder.nextLine(); builder.append(pan); builder.append(editFileTypes); + builder.nextLine(); + + builder.appendSeparator(Localization.lang("Open console")); + builder.nextLine(); + builder.append(new JPanel()); + builder.append(consoleOptionPanel); pan = builder.getPanel(); pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); @@ -113,6 +173,13 @@ public void setValues() { openFoldersOfAttachedFiles.setSelected(prefs.getBoolean(JabRefPreferences.OPEN_FOLDERS_OF_ATTACHED_FILES)); citeCommand.setText(prefs.get(JabRefPreferences.CITE_COMMAND)); + + defaultConsole.setSelected(Globals.prefs.getBoolean(JabRefPreferences.USE_DEFAULT_CONSOLE_APPLICATION)); + executeConsole.setSelected(!Globals.prefs.getBoolean(JabRefPreferences.USE_DEFAULT_CONSOLE_APPLICATION)); + + consoleCommand.setText(Globals.prefs.get(JabRefPreferences.CONSOLE_COMMAND)); + + updateExecuteConsoleButtonAndFieldEnabledState(); } @Override @@ -120,6 +187,8 @@ public void storeSettings() { prefs.put(JabRefPreferences.EMAIL_SUBJECT, emailSubject.getText()); prefs.putBoolean(JabRefPreferences.OPEN_FOLDERS_OF_ATTACHED_FILES, openFoldersOfAttachedFiles.isSelected()); prefs.put(JabRefPreferences.CITE_COMMAND, citeCommand.getText()); + prefs.putBoolean(JabRefPreferences.USE_DEFAULT_CONSOLE_APPLICATION, defaultConsole.isSelected()); + prefs.put(JabRefPreferences.CONSOLE_COMMAND, consoleCommand.getText()); } @Override @@ -131,4 +200,17 @@ public boolean validateSettings() { public String getTabName() { return Localization.lang("External programs"); } + + private void updateExecuteConsoleButtonAndFieldEnabledState() { + browseButton.setEnabled(executeConsole.isSelected()); + consoleCommand.setEnabled(executeConsole.isSelected()); + } + + private void showConsoleChooser() { + JFileChooser consoleChooser = new JFileChooser(); + int answer = consoleChooser.showOpenDialog(ExternalTab.this); + if (answer == JFileChooser.APPROVE_OPTION) { + consoleCommand.setText(consoleChooser.getSelectedFile().getAbsolutePath()); + } + } } diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 4dec88144f5f..1f09d720a84d 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1706,3 +1706,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 43e0ce879f46..853948a7bc8a 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2423,4 +2423,9 @@ Online_help_forum=Online-Hilfeforum Custom= - +Open_console=Terminal_öffnen +Use_default_terminal_emulator=Standard_Terminal-Emulator_verwenden +Execute_command=Befehl_ausführen +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.=Hinweis\:_%0_als_Platzhalter_für_den_Speicherort_der_Datenbank_benutzen. +Executing_command_\"%0\"...=Ausführung_des_Kommandos_\"%0\"... +Error_occured_while_executing_the_command_\"%0\".=Während_der_Ausführung_des_Befehls_\"%0\"_ist_ein_Fehler_aufgetreten. diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 12ac8522ff7d..2e2d6dff0b85 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2272,4 +2272,11 @@ A_new_version_of_JabRef_has_been_released.=A_new_version_of_JabRef_has_been_rele JabRef_is_up-to-date.=JabRef_is_up-to-date. Latest_version=Latest_version Online_help_forum=Online_help_forum -Custom=Custom \ No newline at end of file +Custom=Custom + +Open_console=Open_console +Use_default_terminal_emulator=Use_default_terminal_emulator +Execute_command=Execute_command +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.=Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file. +Executing_command_\"%0\"...=Executing_command_\"%0\"... +Error_occured_while_executing_the_command_\"%0\".=Error_occured_while_executing_the_command_\"%0\". diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 63cab8f118ad..a7c6884fe269 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1608,3 +1608,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index b8e1a33a40ee..2e92ec35fda2 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2394,3 +2394,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index aba12d64823f..576a040f542f 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1652,3 +1652,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 6569ed22c766..24a7595923e5 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1627,3 +1627,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 3764196d33fd..3ae8e350e86b 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1727,3 +1727,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 02947a65c639..b1e8d314abba 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2372,3 +2372,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 774ff9b0a7d8..19016e7e6952 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2403,3 +2403,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 38a65da7b274..e5747132d9bb 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2799,3 +2799,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 71dd268b4fbd..415dd4be244a 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1621,3 +1621,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 0a2a26969746..8e36e2193b40 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2371,3 +2371,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 370b53f700eb..6c2ba56626f8 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1564,3 +1564,10 @@ Online_help_forum=Onlineforum Custom=Egna + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 6db3d61b7e2f..7ae734f66d78 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1640,3 +1640,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index cdd8a3858184..78865a76a746 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2395,3 +2395,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 30d7b51bd6a8..0292f2f0fea7 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1634,3 +1634,10 @@ Online_help_forum= Custom= Converts_HTML_code_to_Unicode.= + +Open_console= +Use_default_terminal_emulator= +Execute_command= +Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= +Executing_command_\"%0\"...= +Error_occured_while_executing_the_command_\"%0\".= From d66e3eb46e91fe8f31e1ffa4901e3689979af1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lenhard?= Date: Tue, 19 Jul 2016 11:54:03 +0200 Subject: [PATCH 249/268] Move preferences (#1604) * Move preferences-related classes into separate package * Rename JabRefPreferencesFilterDialog -> PreferencesFilterDialog and move it to gui * Fix checkstyle warning --- src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java | 2 +- src/main/java/net/sf/jabref/BibDatabaseContext.java | 1 + src/main/java/net/sf/jabref/Globals.java | 1 + src/main/java/net/sf/jabref/JabRefGUI.java | 1 + src/main/java/net/sf/jabref/JabRefMain.java | 1 + src/main/java/net/sf/jabref/cli/ArgumentProcessor.java | 2 +- src/main/java/net/sf/jabref/collab/ChangeScanner.java | 2 +- src/main/java/net/sf/jabref/collab/EntryAddChange.java | 2 +- src/main/java/net/sf/jabref/collab/EntryDeleteChange.java | 2 +- src/main/java/net/sf/jabref/external/AutoSetLinks.java | 2 +- .../sf/jabref/external/ExternalFileTypeEntryEditor.java | 2 +- .../java/net/sf/jabref/external/ExternalFileTypes.java | 2 +- src/main/java/net/sf/jabref/external/MoveFileAction.java | 2 +- .../sf/jabref/external/push/AbstractPushToApplication.java | 2 +- .../sf/jabref/external/push/PushToApplicationButton.java | 2 +- src/main/java/net/sf/jabref/external/push/PushToEmacs.java | 2 +- .../net/sf/jabref/external/push/PushToLatexEditor.java | 2 +- src/main/java/net/sf/jabref/external/push/PushToLyx.java | 2 +- .../java/net/sf/jabref/external/push/PushToTeXstudio.java | 2 +- .../java/net/sf/jabref/external/push/PushToTexmaker.java | 2 +- src/main/java/net/sf/jabref/external/push/PushToVim.java | 2 +- .../java/net/sf/jabref/external/push/PushToWinEdt.java | 2 +- src/main/java/net/sf/jabref/gui/BasePanel.java | 4 ++-- .../java/net/sf/jabref/gui/DuplicateResolverDialog.java | 2 +- src/main/java/net/sf/jabref/gui/EntryMarker.java | 2 +- src/main/java/net/sf/jabref/gui/FileDialogs.java | 2 +- src/main/java/net/sf/jabref/gui/FileListEntryEditor.java | 2 +- .../java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java | 2 +- src/main/java/net/sf/jabref/gui/GUIGlobals.java | 2 +- src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java | 2 +- .../java/net/sf/jabref/gui/ImportInspectionDialog.java | 2 +- src/main/java/net/sf/jabref/gui/JabRefFrame.java | 4 ++-- src/main/java/net/sf/jabref/gui/PreambleEditor.java | 2 +- src/main/java/net/sf/jabref/gui/PreviewPanel.java | 2 +- src/main/java/net/sf/jabref/gui/SidePaneManager.java | 2 +- src/main/java/net/sf/jabref/gui/StringDialog.java | 2 +- src/main/java/net/sf/jabref/gui/actions/CleanupAction.java | 2 +- .../net/sf/jabref/gui/actions/IntegrityCheckAction.java | 2 +- .../net/sf/jabref/gui/actions/NewSubDatabaseAction.java | 2 +- .../java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java | 2 +- src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java | 2 +- .../java/net/sf/jabref/gui/entryeditor/EntryEditor.java | 2 +- .../net/sf/jabref/gui/entryeditor/EntryEditorTabList.java | 2 +- .../sf/jabref/gui/entryeditor/FieldExtraComponents.java | 2 +- .../java/net/sf/jabref/gui/exporter/AutoSaveManager.java | 2 +- .../net/sf/jabref/gui/exporter/CustomExportDialog.java | 2 +- src/main/java/net/sf/jabref/gui/exporter/ExportAction.java | 2 +- .../net/sf/jabref/gui/exporter/SaveDatabaseAction.java | 2 +- .../jabref/gui/fieldeditors/JTextAreaWithHighlighting.java | 2 +- src/main/java/net/sf/jabref/gui/groups/GroupDialog.java | 2 +- src/main/java/net/sf/jabref/gui/groups/GroupSelector.java | 2 +- .../net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java | 2 +- src/main/java/net/sf/jabref/gui/groups/GroupsTree.java | 2 +- src/main/java/net/sf/jabref/gui/help/HelpAction.java | 2 +- .../net/sf/jabref/gui/journals/ManageJournalsPanel.java | 2 +- .../java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java | 2 +- .../net/sf/jabref/gui/keyboard/KeyBindingPreferences.java | 2 +- .../net/sf/jabref/gui/labelpattern/LabelPatternPanel.java | 2 +- src/main/java/net/sf/jabref/gui/maintable/MainTable.java | 2 +- .../java/net/sf/jabref/gui/maintable/MainTableFormat.java | 2 +- .../sf/jabref/gui/maintable/MainTableNameFormatter.java | 2 +- .../jabref/gui/maintable/MainTableSelectionListener.java | 2 +- .../gui/maintable/PersistenceTableColumnListener.java | 2 +- src/main/java/net/sf/jabref/gui/menus/FileHistoryMenu.java | 2 +- src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java | 2 +- .../java/net/sf/jabref/gui/mergeentries/MergeEntries.java | 2 +- .../net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java | 2 +- .../sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java | 2 +- .../net/sf/jabref/gui/openoffice/StyleSelectDialog.java | 2 +- .../net/sf/jabref/gui/plaintextimport/TextInputDialog.java | 2 +- src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java | 2 +- .../net/sf/jabref/gui/preftabs/AppearancePrefsTab.java | 2 +- .../java/net/sf/jabref/gui/preftabs/ColorSetupPanel.java | 2 +- .../net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java | 2 +- src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java | 2 +- src/main/java/net/sf/jabref/gui/preftabs/FileSortTab.java | 2 +- src/main/java/net/sf/jabref/gui/preftabs/FileTab.java | 2 +- src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java | 2 +- .../java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java | 2 +- .../java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java | 2 +- .../net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java | 2 +- .../java/net/sf/jabref/gui/preftabs/NameFormatterTab.java | 2 +- src/main/java/net/sf/jabref/gui/preftabs/NetworkTab.java | 2 +- .../java/net/sf/jabref/gui/preftabs/PreferencesDialog.java | 7 +++---- .../preftabs/PreferencesFilterDialog.java} | 7 ++++--- .../java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java | 2 +- .../java/net/sf/jabref/gui/preftabs/TableColumnsTab.java | 2 +- .../java/net/sf/jabref/gui/preftabs/TablePrefsTab.java | 2 +- src/main/java/net/sf/jabref/gui/preftabs/XmpPrefsTab.java | 2 +- .../net/sf/jabref/gui/renderer/IncompleteRenderer.java | 2 +- src/main/java/net/sf/jabref/gui/search/SearchBar.java | 2 +- .../java/net/sf/jabref/gui/search/SearchResultsDialog.java | 2 +- .../java/net/sf/jabref/gui/worker/MarkEntriesAction.java | 2 +- .../java/net/sf/jabref/gui/worker/SendAsEMailAction.java | 2 +- .../java/net/sf/jabref/importer/AppendDatabaseAction.java | 2 +- .../net/sf/jabref/importer/AutosaveStartupPrompter.java | 2 +- .../sf/jabref/importer/CheckForNewEntryTypesAction.java | 2 +- src/main/java/net/sf/jabref/importer/CustomImportList.java | 2 +- .../net/sf/jabref/importer/ImportCustomizationDialog.java | 2 +- src/main/java/net/sf/jabref/importer/ImportFormats.java | 2 +- src/main/java/net/sf/jabref/importer/ImportMenuItem.java | 2 +- .../java/net/sf/jabref/importer/OpenDatabaseAction.java | 2 +- .../net/sf/jabref/importer/fetcher/ACMPortalFetcher.java | 2 +- .../jabref/importer/fetcher/CrossrefFetcherEvaluator.java | 2 +- .../net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java | 2 +- .../sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java | 2 +- .../net/sf/jabref/importer/fetcher/GeneralFetcher.java | 2 +- .../net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java | 2 +- .../sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java | 2 +- .../java/net/sf/jabref/logic/CustomEntryTypesManager.java | 2 +- .../logic/autocompleter/AutoCompletePreferences.java | 2 +- .../net/sf/jabref/logic/bibtex/FieldContentParser.java | 2 +- .../net/sf/jabref/logic/bibtex/LatexFieldFormatter.java | 2 +- .../java/net/sf/jabref/logic/cleanup/CleanupPreset.java | 2 +- .../java/net/sf/jabref/logic/config/SaveOrderConfig.java | 2 +- .../net/sf/jabref/logic/exporter/CustomExportList.java | 2 +- .../java/net/sf/jabref/logic/exporter/FileSaveSession.java | 2 +- .../java/net/sf/jabref/logic/exporter/SavePreferences.java | 2 +- .../logic/formatter/bibtexfields/HtmlToLatexFormatter.java | 2 +- src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java | 2 +- src/main/java/net/sf/jabref/logic/groups/SearchGroup.java | 2 +- .../jabref/logic/journals/JournalAbbreviationLoader.java | 2 +- .../net/sf/jabref/logic/labelpattern/LabelPatternUtil.java | 2 +- .../java/net/sf/jabref/logic/net/ProxyPreferences.java | 2 +- .../sf/jabref/logic/openoffice/OpenOfficePreferences.java | 2 +- .../logic/preferences/LastFocusedTabPreferences.java | 2 +- .../java/net/sf/jabref/logic/remote/RemotePreferences.java | 2 +- src/main/java/net/sf/jabref/logic/util/UpdateField.java | 2 +- .../java/net/sf/jabref/logic/util/VersionPreferences.java | 2 +- .../java/net/sf/jabref/logic/util/date/EasyDateFormat.java | 2 +- src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java | 2 +- src/main/java/net/sf/jabref/logic/util/io/FileHistory.java | 2 +- src/main/java/net/sf/jabref/logic/util/io/FileUtil.java | 2 +- src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java | 2 +- src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java | 2 +- .../net/sf/jabref/migrations/FileLinksUpgradeWarning.java | 2 +- .../net/sf/jabref/migrations/PreferencesMigrations.java | 2 +- src/main/java/net/sf/jabref/model/entry/BibEntry.java | 2 +- .../net/sf/jabref/model/entry/InternalBibtexFields.java | 2 +- src/main/java/net/sf/jabref/pdfimport/ImportDialog.java | 2 +- src/main/java/net/sf/jabref/pdfimport/PdfImporter.java | 2 +- .../HighlightMatchingGroupPreferences.java | 2 +- .../net/sf/jabref/{ => preferences}/JabRefPreferences.java | 4 +++- .../jabref/{ => preferences}/JabRefPreferencesFilter.java | 2 +- src/main/java/net/sf/jabref/sql/DBStringsPreferences.java | 2 +- src/test/java/net/sf/jabref/BibDatabaseContextTest.java | 1 + src/test/java/net/sf/jabref/FileBasedTestCase.java | 1 + src/test/java/net/sf/jabref/JabRefPreferencesTest.java | 2 ++ src/test/java/net/sf/jabref/MetaDataTest.java | 1 + .../net/sf/jabref/SearchQueryHighlightListenerTest.java | 1 + src/test/java/net/sf/jabref/cli/AuxCommandLineTest.java | 2 +- .../java/net/sf/jabref/external/RegExpFileSearchTests.java | 2 +- .../jabref/importer/ConvertLegacyExplicitGroupsTest.java | 2 +- .../net/sf/jabref/importer/DatabaseFileLookupTest.java | 2 +- .../jabref/importer/EntryFromFileCreatorManagerTest.java | 2 +- .../net/sf/jabref/importer/EntryFromPDFCreatorTest.java | 2 +- .../jabref/importer/ImportFormatReaderIntegrationTest.java | 2 +- .../importer/ImportFormatReaderTestParameterless.java | 2 +- .../net/sf/jabref/importer/OpenDatabaseActionTest.java | 2 +- .../java/net/sf/jabref/importer/fetcher/GVKParserTest.java | 2 +- .../jabref/importer/fileformat/BibTeXMLImporterTest.java | 2 +- .../importer/fileformat/BibTeXMLImporterTestFiles.java | 2 +- .../importer/fileformat/BibTeXMLImporterTestTypes.java | 2 +- .../importer/fileformat/BiblioscapeImporterTest.java | 2 +- .../importer/fileformat/BiblioscapeImporterTestFiles.java | 2 +- .../importer/fileformat/BiblioscapeImporterTestTypes.java | 2 +- .../sf/jabref/importer/fileformat/BibtexImporterTest.java | 2 +- .../sf/jabref/importer/fileformat/BibtexParserTest.java | 2 +- .../sf/jabref/importer/fileformat/CopacImporterTest.java | 2 +- .../jabref/importer/fileformat/CopacImporterTestFiles.java | 2 +- .../sf/jabref/importer/fileformat/EndnoteImporterTest.java | 2 +- .../jabref/importer/fileformat/FreeCiteImporterTest.java | 2 +- .../sf/jabref/importer/fileformat/InspecImportTest.java | 2 +- .../net/sf/jabref/importer/fileformat/IsiImporterTest.java | 2 +- .../sf/jabref/importer/fileformat/MedlineImporterTest.java | 2 +- .../importer/fileformat/MedlineImporterTestFiles.java | 2 +- .../importer/fileformat/MedlinePlainImporterTest.java | 2 +- .../sf/jabref/importer/fileformat/MsBibImporterTest.java | 2 +- .../jabref/importer/fileformat/MsBibImporterTestfiles.java | 2 +- .../sf/jabref/importer/fileformat/OvidImporterTest.java | 2 +- .../importer/fileformat/PdfContentImporterTestFiles.java | 2 +- .../sf/jabref/importer/fileformat/PdfXmpImporterTest.java | 2 +- .../net/sf/jabref/importer/fileformat/RISImporterTest.java | 2 +- .../jabref/importer/fileformat/RISImporterTestFiles.java | 2 +- .../jabref/importer/fileformat/RepecNepImporterTest.java | 2 +- .../importer/fileformat/SilverPlatterImporterTest.java | 2 +- .../fileformat/SilverPlatterImporterTestNotRecognized.java | 2 +- .../java/net/sf/jabref/logic/auxparser/AuxParserTest.java | 2 +- .../net/sf/jabref/logic/bibtex/BibEntryWriterTest.java | 2 +- .../net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java | 2 +- .../net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java | 2 +- .../net/sf/jabref/logic/bibtex/FieldContentParserTest.java | 2 +- .../sf/jabref/logic/bibtex/LatexFieldFormatterTests.java | 2 +- src/test/java/net/sf/jabref/logic/bst/TestVM.java | 2 +- .../net/sf/jabref/logic/cleanup/CleanupWorkerTest.java | 2 +- .../net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java | 2 +- .../net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java | 2 +- .../sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java | 2 +- .../net/sf/jabref/logic/exporter/ExportFormatTest.java | 2 +- .../jabref/logic/exporter/FieldFormatterCleanupsTest.java | 2 +- .../net/sf/jabref/logic/exporter/HtmlExportFormatTest.java | 2 +- .../jabref/logic/exporter/MSBibExportFormatTestFiles.java | 2 +- .../sf/jabref/logic/exporter/MsBibExportFormatTest.java | 2 +- .../java/net/sf/jabref/logic/formatter/FormatterTest.java | 2 +- .../formatter/bibtexfields/HtmlToLatexFormatterTest.java | 2 +- .../logic/formatter/bibtexfields/UnicodeConverterTest.java | 2 +- .../java/net/sf/jabref/logic/groups/ExplicitGroupTest.java | 2 +- .../java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java | 2 +- .../java/net/sf/jabref/logic/groups/GroupsUtilTest.java | 2 +- .../java/net/sf/jabref/logic/groups/SearchGroupTest.java | 2 +- .../net/sf/jabref/logic/integrity/IntegrityCheckTest.java | 2 +- .../net/sf/jabref/logic/journals/AbbreviationsTest.java | 2 +- .../java/net/sf/jabref/logic/l10n/LocalizationTest.java | 2 +- .../sf/jabref/logic/labelpattern/LabelPatternUtilTest.java | 2 +- .../java/net/sf/jabref/logic/layout/LayoutEntryTest.java | 2 +- src/test/java/net/sf/jabref/logic/layout/LayoutTest.java | 2 +- .../net/sf/jabref/logic/layout/format/FileLinkTest.java | 2 +- src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java | 2 +- .../net/sf/jabref/logic/openoffice/OOBibStyleTest.java | 2 +- .../net/sf/jabref/logic/openoffice/StyleLoaderTest.java | 2 +- .../logic/preferences/LastFocusedTabPreferencesTest.java | 2 +- .../net/sf/jabref/logic/search/MatchesHighlighterTest.java | 2 +- .../logic/search/rules/ContainBasedSearchRuleTest.java | 2 +- .../java/net/sf/jabref/logic/util/io/FileHistoryTest.java | 2 +- .../java/net/sf/jabref/logic/util/io/FileUtilTest.java | 2 +- .../net/sf/jabref/logic/util/strings/StringUtilTest.java | 2 +- .../java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java | 2 +- src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java | 2 +- src/test/java/net/sf/jabref/model/DuplicateCheckTest.java | 2 +- .../java/net/sf/jabref/model/database/BibDatabaseTest.java | 2 +- src/test/java/net/sf/jabref/model/entry/BibEntryTests.java | 2 +- .../java/net/sf/jabref/sql/DatabaseImportExportTests.java | 2 +- 232 files changed, 242 insertions(+), 230 deletions(-) rename src/main/java/net/sf/jabref/{JabRefPreferencesFilterDialog.java => gui/preftabs/PreferencesFilterDialog.java} (94%) rename src/main/java/net/sf/jabref/{ => preferences}/HighlightMatchingGroupPreferences.java (96%) rename src/main/java/net/sf/jabref/{ => preferences}/JabRefPreferences.java (99%) rename src/main/java/net/sf/jabref/{ => preferences}/JabRefPreferencesFilter.java (98%) diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index c62681edd421..e1a03ce04233 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -10,7 +10,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -28,6 +27,7 @@ import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.database.BibDatabaseModeDetection; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.openjdk.jmh.Main; import org.openjdk.jmh.annotations.Benchmark; diff --git a/src/main/java/net/sf/jabref/BibDatabaseContext.java b/src/main/java/net/sf/jabref/BibDatabaseContext.java index 7fc9ca296595..6f95ff4f1d89 100644 --- a/src/main/java/net/sf/jabref/BibDatabaseContext.java +++ b/src/main/java/net/sf/jabref/BibDatabaseContext.java @@ -9,6 +9,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.database.BibDatabaseModeDetection; +import net.sf.jabref.preferences.JabRefPreferences; /** * Represents everything related to a .bib file. diff --git a/src/main/java/net/sf/jabref/Globals.java b/src/main/java/net/sf/jabref/Globals.java index c51932db8dbd..df3c3cfd94c6 100644 --- a/src/main/java/net/sf/jabref/Globals.java +++ b/src/main/java/net/sf/jabref/Globals.java @@ -27,6 +27,7 @@ import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.remote.server.RemoteListenerServerLifecycle; import net.sf.jabref.logic.util.BuildInfo; +import net.sf.jabref.preferences.JabRefPreferences; public class Globals { diff --git a/src/main/java/net/sf/jabref/JabRefGUI.java b/src/main/java/net/sf/jabref/JabRefGUI.java index b63bafc3e95a..49b662487c9e 100644 --- a/src/main/java/net/sf/jabref/JabRefGUI.java +++ b/src/main/java/net/sf/jabref/JabRefGUI.java @@ -46,6 +46,7 @@ import net.sf.jabref.logic.util.Version; import net.sf.jabref.logic.util.VersionPreferences; import net.sf.jabref.migrations.PreferencesMigrations; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; import com.jgoodies.looks.plastic.theme.SkyBluer; diff --git a/src/main/java/net/sf/jabref/JabRefMain.java b/src/main/java/net/sf/jabref/JabRefMain.java index e825a28a9172..48329e11b43d 100644 --- a/src/main/java/net/sf/jabref/JabRefMain.java +++ b/src/main/java/net/sf/jabref/JabRefMain.java @@ -31,6 +31,7 @@ import net.sf.jabref.logic.remote.RemotePreferences; import net.sf.jabref.logic.remote.client.RemoteListenerClient; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java index f8212c7d3b02..cfc25c77d115 100644 --- a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java @@ -17,7 +17,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefException; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.external.AutoSetLinks; import net.sf.jabref.importer.ImportFormatReader; @@ -45,6 +44,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index 106fc148d10a..ab9987a9a42a 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -33,7 +33,6 @@ import net.sf.jabref.Defaults; import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; @@ -54,6 +53,7 @@ import net.sf.jabref.model.database.EntrySorter; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/collab/EntryAddChange.java b/src/main/java/net/sf/jabref/collab/EntryAddChange.java index 3efcc803c9e8..2208a72082da 100644 --- a/src/main/java/net/sf/jabref/collab/EntryAddChange.java +++ b/src/main/java/net/sf/jabref/collab/EntryAddChange.java @@ -19,7 +19,6 @@ import javax.swing.JScrollPane; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.PreviewPanel; import net.sf.jabref.gui.undo.NamedCompound; @@ -28,6 +27,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; class EntryAddChange extends Change { diff --git a/src/main/java/net/sf/jabref/collab/EntryDeleteChange.java b/src/main/java/net/sf/jabref/collab/EntryDeleteChange.java index f9f2ca0badf8..b874b0725c8e 100644 --- a/src/main/java/net/sf/jabref/collab/EntryDeleteChange.java +++ b/src/main/java/net/sf/jabref/collab/EntryDeleteChange.java @@ -19,7 +19,6 @@ import javax.swing.JScrollPane; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.PreviewPanel; import net.sf.jabref.gui.undo.NamedCompound; @@ -28,6 +27,7 @@ import net.sf.jabref.model.DuplicateCheck; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/external/AutoSetLinks.java b/src/main/java/net/sf/jabref/external/AutoSetLinks.java index bc57847d50ea..7346c9e48619 100644 --- a/src/main/java/net/sf/jabref/external/AutoSetLinks.java +++ b/src/main/java/net/sf/jabref/external/AutoSetLinks.java @@ -22,7 +22,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.undo.NamedCompound; @@ -30,6 +29,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; public class AutoSetLinks { diff --git a/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java b/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java index 99ceaf30c468..b584e79ea441 100644 --- a/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java +++ b/src/main/java/net/sf/jabref/external/ExternalFileTypeEntryEditor.java @@ -36,11 +36,11 @@ import javax.swing.event.DocumentListener; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.FormBuilder; diff --git a/src/main/java/net/sf/jabref/external/ExternalFileTypes.java b/src/main/java/net/sf/jabref/external/ExternalFileTypes.java index c409f01ba12d..8c84ff180470 100644 --- a/src/main/java/net/sf/jabref/external/ExternalFileTypes.java +++ b/src/main/java/net/sf/jabref/external/ExternalFileTypes.java @@ -8,11 +8,11 @@ import java.util.TreeSet; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.FileField; +import net.sf.jabref.preferences.JabRefPreferences; public final class ExternalFileTypes { diff --git a/src/main/java/net/sf/jabref/external/MoveFileAction.java b/src/main/java/net/sf/jabref/external/MoveFileAction.java index 4167851531f8..d39339c4b05d 100644 --- a/src/main/java/net/sf/jabref/external/MoveFileAction.java +++ b/src/main/java/net/sf/jabref/external/MoveFileAction.java @@ -27,7 +27,6 @@ import javax.swing.JOptionPane; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.JabRefFrame; @@ -36,6 +35,7 @@ import net.sf.jabref.gui.util.component.CheckBoxMessage; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/external/push/AbstractPushToApplication.java b/src/main/java/net/sf/jabref/external/push/AbstractPushToApplication.java index 3713d4a9ecbe..0899848b8dcb 100644 --- a/src/main/java/net/sf/jabref/external/push/AbstractPushToApplication.java +++ b/src/main/java/net/sf/jabref/external/push/AbstractPushToApplication.java @@ -24,13 +24,13 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.actions.BrowseAction; 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.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/external/push/PushToApplicationButton.java b/src/main/java/net/sf/jabref/external/push/PushToApplicationButton.java index 0252b8310d09..59dc83d9b5c1 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToApplicationButton.java +++ b/src/main/java/net/sf/jabref/external/push/PushToApplicationButton.java @@ -42,13 +42,13 @@ import javax.swing.JPopupMenu; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; diff --git a/src/main/java/net/sf/jabref/external/push/PushToEmacs.java b/src/main/java/net/sf/jabref/external/push/PushToEmacs.java index a82f86a8ba11..8c7af57028fc 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToEmacs.java +++ b/src/main/java/net/sf/jabref/external/push/PushToEmacs.java @@ -27,7 +27,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; @@ -35,6 +34,7 @@ import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/external/push/PushToLatexEditor.java b/src/main/java/net/sf/jabref/external/push/PushToLatexEditor.java index ae72f7275728..b81d1ccb034d 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToLatexEditor.java +++ b/src/main/java/net/sf/jabref/external/push/PushToLatexEditor.java @@ -17,8 +17,8 @@ import javax.swing.Icon; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; +import net.sf.jabref.preferences.JabRefPreferences; /** * Class for pushing entries into LatexEditor. diff --git a/src/main/java/net/sf/jabref/external/push/PushToLyx.java b/src/main/java/net/sf/jabref/external/push/PushToLyx.java index 6df3a0b5b882..96bcfc5d3404 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToLyx.java +++ b/src/main/java/net/sf/jabref/external/push/PushToLyx.java @@ -27,13 +27,13 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; 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.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/external/push/PushToTeXstudio.java b/src/main/java/net/sf/jabref/external/push/PushToTeXstudio.java index 07ddc27e043f..96b16d7aa7e9 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToTeXstudio.java +++ b/src/main/java/net/sf/jabref/external/push/PushToTeXstudio.java @@ -17,8 +17,8 @@ import javax.swing.Icon; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; +import net.sf.jabref.preferences.JabRefPreferences; /** * Created by IntelliJ IDEA. User: alver Date: Jan 14, 2006 Time: 4:55:23 PM To change this template use File | Settings diff --git a/src/main/java/net/sf/jabref/external/push/PushToTexmaker.java b/src/main/java/net/sf/jabref/external/push/PushToTexmaker.java index 59856d980998..5caaead3108d 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToTexmaker.java +++ b/src/main/java/net/sf/jabref/external/push/PushToTexmaker.java @@ -18,8 +18,8 @@ import javax.swing.Icon; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; +import net.sf.jabref.preferences.JabRefPreferences; /** * Class for pushing entries into TexMaker. diff --git a/src/main/java/net/sf/jabref/external/push/PushToVim.java b/src/main/java/net/sf/jabref/external/push/PushToVim.java index c45cb330a3d3..805dd56b913c 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToVim.java +++ b/src/main/java/net/sf/jabref/external/push/PushToVim.java @@ -26,13 +26,13 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; 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.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/external/push/PushToWinEdt.java b/src/main/java/net/sf/jabref/external/push/PushToWinEdt.java index be21e781381a..dd150b15663d 100644 --- a/src/main/java/net/sf/jabref/external/push/PushToWinEdt.java +++ b/src/main/java/net/sf/jabref/external/push/PushToWinEdt.java @@ -17,8 +17,8 @@ import javax.swing.Icon; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; +import net.sf.jabref.preferences.JabRefPreferences; public class PushToWinEdt extends AbstractPushToApplication implements PushToApplication { diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 0765ed943b29..2a7e11a13a07 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -55,9 +55,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.HighlightMatchingGroupPreferences; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.collab.ChangeScanner; import net.sf.jabref.collab.FileUpdateListener; import net.sf.jabref.collab.FileUpdatePanel; @@ -131,6 +129,8 @@ import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.event.EntryAddedEvent; import net.sf.jabref.model.event.EntryChangedEvent; +import net.sf.jabref.preferences.HighlightMatchingGroupPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; diff --git a/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java b/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java index ae17efc1af91..0a5836602fbc 100644 --- a/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java +++ b/src/main/java/net/sf/jabref/gui/DuplicateResolverDialog.java @@ -22,11 +22,11 @@ import javax.swing.JDialog; import javax.swing.JPanel; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.mergeentries.MergeEntries; import net.sf.jabref.gui.util.PositionWindow; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; // created by : ? // diff --git a/src/main/java/net/sf/jabref/gui/EntryMarker.java b/src/main/java/net/sf/jabref/gui/EntryMarker.java index 60ba56bbb77c..cd8ce7987d05 100644 --- a/src/main/java/net/sf/jabref/gui/EntryMarker.java +++ b/src/main/java/net/sf/jabref/gui/EntryMarker.java @@ -21,12 +21,12 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; public class EntryMarker { diff --git a/src/main/java/net/sf/jabref/gui/FileDialogs.java b/src/main/java/net/sf/jabref/gui/FileDialogs.java index de93d9657cec..0a050e0b890a 100644 --- a/src/main/java/net/sf/jabref/gui/FileDialogs.java +++ b/src/main/java/net/sf/jabref/gui/FileDialogs.java @@ -26,8 +26,8 @@ import javax.swing.JFrame; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.preferences.JabRefPreferences; public class FileDialogs { diff --git a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java index 2858bffadf34..7d6ebfb45d55 100644 --- a/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/FileListEntryEditor.java @@ -49,7 +49,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ConfirmCloseFileListEntryEditor; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; @@ -58,6 +57,7 @@ import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.FormBuilder; diff --git a/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java b/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java index c8b3d4f06096..f67e3b666ba7 100644 --- a/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java +++ b/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java @@ -82,7 +82,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.importer.EntryFromFileCreator; import net.sf.jabref.importer.EntryFromFileCreatorManager; @@ -92,6 +91,7 @@ import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/gui/GUIGlobals.java b/src/main/java/net/sf/jabref/gui/GUIGlobals.java index 92b02709f434..f5a5e38b2169 100644 --- a/src/main/java/net/sf/jabref/gui/GUIGlobals.java +++ b/src/main/java/net/sf/jabref/gui/GUIGlobals.java @@ -23,11 +23,11 @@ import javax.swing.JLabel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.gui.keyboard.EmacsKeyBindings; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; diff --git a/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java b/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java index 8dea8268671b..a688fe08cc52 100644 --- a/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java +++ b/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java @@ -36,13 +36,13 @@ import javax.swing.JTextArea; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.layout.Sizes; diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 712cd92e3686..85e0ec273de2 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -68,7 +68,6 @@ import net.sf.jabref.Defaults; import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.external.DownloadExternalFile; import net.sf.jabref.external.ExternalFileMenuItem; @@ -103,6 +102,7 @@ import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 5613c04e2409..c3c7a04ed296 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -71,9 +71,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.HighlightMatchingGroupPreferences; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileTypeEditor; import net.sf.jabref.external.push.PushToApplicationButton; import net.sf.jabref.external.push.PushToApplications; @@ -130,6 +128,8 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.preferences.HighlightMatchingGroupPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; diff --git a/src/main/java/net/sf/jabref/gui/PreambleEditor.java b/src/main/java/net/sf/jabref/gui/PreambleEditor.java index c8caf09fe234..75d5013e39e5 100644 --- a/src/main/java/net/sf/jabref/gui/PreambleEditor.java +++ b/src/main/java/net/sf/jabref/gui/PreambleEditor.java @@ -35,7 +35,6 @@ import javax.swing.text.JTextComponent; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.fieldeditors.FieldEditor; import net.sf.jabref.gui.fieldeditors.TextArea; @@ -44,6 +43,7 @@ import net.sf.jabref.gui.util.PositionWindow; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.preferences.JabRefPreferences; class PreambleEditor extends JDialog { // A reference to the entry this object works on. diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index e697755a020e..e0bcca474347 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -49,7 +49,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.fieldeditors.PreviewPanelTransferHandler; import net.sf.jabref.gui.keyboard.KeyBinding; @@ -60,6 +59,7 @@ import net.sf.jabref.logic.search.SearchQueryHighlightListener; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.event.FieldChangedEvent; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.eventbus.Subscribe; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/gui/SidePaneManager.java b/src/main/java/net/sf/jabref/gui/SidePaneManager.java index 4187135f74bc..231fc6cc2357 100644 --- a/src/main/java/net/sf/jabref/gui/SidePaneManager.java +++ b/src/main/java/net/sf/jabref/gui/SidePaneManager.java @@ -28,7 +28,7 @@ import javax.swing.SwingUtilities; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index 10b622d23d42..a0c6f6074630 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -46,7 +46,6 @@ import javax.swing.undo.CompoundEdit; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; @@ -62,6 +61,7 @@ import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; class StringDialog extends JDialog { diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java index d160b029324b..a41b5b68d161 100644 --- a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java @@ -22,7 +22,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.cleanup.CleanupPresetPanel; @@ -35,6 +34,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; public class CleanupAction extends AbstractWorker { diff --git a/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java b/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java index b9757fbe6131..77084fba6eb6 100644 --- a/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java @@ -11,11 +11,11 @@ import javax.swing.ListSelectionModel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.logic.integrity.IntegrityCheck; import net.sf.jabref.logic.integrity.IntegrityMessage; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; public class IntegrityCheckAction extends MnemonicAwareAction { diff --git a/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java b/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java index a8702734f49c..c22d70b7a410 100644 --- a/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java @@ -7,13 +7,13 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.auximport.FromAuxDialog; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.preferences.JabRefPreferences; /** * The action concerned with generate a new (sub-)database from latex aux file. diff --git a/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java b/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java index 3bb7c8161be1..b3b775cac07b 100644 --- a/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java +++ b/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java @@ -10,9 +10,9 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.cleanup.CleanupPreset; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index f85695149a2f..d5c126bae2c3 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -28,7 +28,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypeEntryEditor; import net.sf.jabref.external.ExternalFileTypes; @@ -50,6 +49,7 @@ import net.sf.jabref.logic.util.OS; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 46f51444f44b..95ee322e314b 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -64,7 +64,6 @@ import javax.swing.text.JTextComponent; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.WriteXMPEntryEditorAction; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryContainer; @@ -110,6 +109,7 @@ import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.event.FieldChangedEvent; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldUpdateListener; import com.google.common.eventbus.Subscribe; diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabList.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabList.java index ad922994cc81..42b62dd03ab0 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabList.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabList.java @@ -20,7 +20,7 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; /** * Class for holding the information about customizable entry editor tabs. diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index cf6d4e7215cc..9581d91a74f0 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -36,7 +36,6 @@ import javax.swing.text.JTextComponent; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FieldContentSelector; import net.sf.jabref.gui.JabRefFrame; @@ -56,6 +55,7 @@ import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; +import net.sf.jabref.preferences.JabRefPreferences; public class FieldExtraComponents { diff --git a/src/main/java/net/sf/jabref/gui/exporter/AutoSaveManager.java b/src/main/java/net/sf/jabref/gui/exporter/AutoSaveManager.java index a94d78e063fd..e1e06b55b0ed 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/AutoSaveManager.java +++ b/src/main/java/net/sf/jabref/gui/exporter/AutoSaveManager.java @@ -20,7 +20,6 @@ import java.util.TimerTask; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.logic.exporter.BibDatabaseWriter; @@ -29,6 +28,7 @@ import net.sf.jabref.logic.exporter.SaveException; import net.sf.jabref.logic.exporter.SavePreferences; import net.sf.jabref.logic.exporter.SaveSession; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/exporter/CustomExportDialog.java b/src/main/java/net/sf/jabref/gui/exporter/CustomExportDialog.java index f68817af2f2a..706bf9c00ee4 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/CustomExportDialog.java +++ b/src/main/java/net/sf/jabref/gui/exporter/CustomExportDialog.java @@ -37,11 +37,11 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; diff --git a/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java b/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java index 6686265d0356..6df4e75a6abd 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java @@ -14,7 +14,6 @@ import javax.swing.filechooser.FileFilter; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.worker.AbstractWorker; @@ -22,6 +21,7 @@ import net.sf.jabref.logic.exporter.IExportFormat; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/net/sf/jabref/gui/exporter/SaveDatabaseAction.java index fb4f516716b8..a36a6593518f 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/net/sf/jabref/gui/exporter/SaveDatabaseAction.java @@ -29,7 +29,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.collab.ChangeScanner; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileDialogs; @@ -45,6 +44,7 @@ import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileBasedLock; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/JTextAreaWithHighlighting.java b/src/main/java/net/sf/jabref/gui/fieldeditors/JTextAreaWithHighlighting.java index 0a3a4c673d94..12fbb197178a 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/JTextAreaWithHighlighting.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/JTextAreaWithHighlighting.java @@ -33,10 +33,10 @@ import javax.swing.undo.UndoManager; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.actions.PasteAction; import net.sf.jabref.logic.search.SearchQueryHighlightListener; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index 37d8f9847d30..a5aa095174d2 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -43,7 +43,6 @@ import javax.swing.event.CaretListener; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FieldContentSelector; import net.sf.jabref.gui.JabRefFrame; @@ -58,6 +57,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.DefaultFormBuilder; diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index c4791b575f55..247f3cc3b0a6 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -58,7 +58,6 @@ import javax.swing.undo.CompoundEdit; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; @@ -81,6 +80,7 @@ import net.sf.jabref.logic.search.matchers.MatcherSets; import net.sf.jabref.logic.search.matchers.NotMatcher; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java index 74435a804926..1d2706592eef 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -34,7 +34,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.undo.CountingUndoManager; @@ -44,6 +43,7 @@ import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.groups.MoveGroupChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; public class GroupTreeNodeViewModel implements Transferable, TreeNode { diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java index 052389bd2443..d44edaac83e6 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupsTree.java @@ -50,12 +50,12 @@ import javax.swing.tree.TreeSelectionModel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.groups.MoveGroupChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; public class GroupsTree extends JTree implements DragSourceListener, DropTargetListener, DragGestureListener { diff --git a/src/main/java/net/sf/jabref/gui/help/HelpAction.java b/src/main/java/net/sf/jabref/gui/help/HelpAction.java index 20c50cdb9863..a01103f81613 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpAction.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpAction.java @@ -24,11 +24,11 @@ import javax.swing.KeyStroke; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java index d44b17311251..3cd0c8e41242 100644 --- a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java +++ b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java @@ -57,7 +57,6 @@ import javax.swing.table.AbstractTableModel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; @@ -68,6 +67,7 @@ import net.sf.jabref.logic.journals.Abbreviation; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.ButtonStackBuilder; diff --git a/src/main/java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java b/src/main/java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java index 8ff24a771c60..8f650dafc61b 100644 --- a/src/main/java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java +++ b/src/main/java/net/sf/jabref/gui/keyboard/EmacsKeyBindings.java @@ -62,7 +62,7 @@ import javax.swing.text.TextAction; import javax.swing.text.Utilities; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingPreferences.java b/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingPreferences.java index 2671adc9432f..ad6d2d02fc58 100644 --- a/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingPreferences.java +++ b/src/main/java/net/sf/jabref/gui/keyboard/KeyBindingPreferences.java @@ -12,8 +12,8 @@ import javax.swing.KeyStroke; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java index 80943e74f9d0..2e72afc14aff 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java @@ -32,7 +32,6 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.help.HelpAction; @@ -44,6 +43,7 @@ import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.preferences.JabRefPreferences; public class LabelPatternPanel extends JPanel { diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java index be69f02a1867..7820447c2531 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java @@ -39,7 +39,6 @@ import javax.swing.table.TableColumnModel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryMarker; import net.sf.jabref.gui.GUIGlobals; @@ -59,6 +58,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexSingleField; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; import ca.odell.glazedlists.EventList; diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java index fb18c38ba196..a1067fd3d521 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java @@ -23,10 +23,10 @@ import javax.swing.JLabel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; import ca.odell.glazedlists.gui.TableFormat; diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableNameFormatter.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableNameFormatter.java index aeb33994b2e4..340ae150dfa1 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableNameFormatter.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableNameFormatter.java @@ -1,8 +1,8 @@ package net.sf.jabref.gui.maintable; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.AuthorList; +import net.sf.jabref.preferences.JabRefPreferences; public class MainTableNameFormatter { diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index 27ceed50cfa5..9bc835e31486 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -34,7 +34,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileMenuItem; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.BasePanelMode; @@ -50,6 +49,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldValue; import net.sf.jabref.specialfields.SpecialFieldsUtils; diff --git a/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java b/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java index 53dc68764168..bcee332a5458 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/PersistenceTableColumnListener.java @@ -24,8 +24,8 @@ import javax.swing.event.TableColumnModelListener; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; /** * Listens for TableColumnModelEvents to keep track of changes made to the diff --git a/src/main/java/net/sf/jabref/gui/menus/FileHistoryMenu.java b/src/main/java/net/sf/jabref/gui/menus/FileHistoryMenu.java index 75c76035bbed..25139650861d 100644 --- a/src/main/java/net/sf/jabref/gui/menus/FileHistoryMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/FileHistoryMenu.java @@ -24,10 +24,10 @@ import javax.swing.JOptionPane; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileHistory; +import net.sf.jabref.preferences.JabRefPreferences; public class FileHistoryMenu extends JMenu implements ActionListener { diff --git a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java index 8d1bbd7b2e5b..111aab887eb2 100644 --- a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java @@ -29,7 +29,6 @@ import javax.swing.event.PopupMenuListener; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryMarker; import net.sf.jabref.gui.FileListTableModel; @@ -41,6 +40,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java index 8b58071c2a83..7bdf6b01caae 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java @@ -43,7 +43,6 @@ import javax.swing.text.html.StyleSheet; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.PreviewPanel; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; @@ -53,6 +52,7 @@ import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.ColumnSpec; diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java index 931fe768d498..b3803cde2fcd 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntriesDialog.java @@ -22,7 +22,6 @@ import javax.swing.JOptionPane; import javax.swing.JSeparator; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableInsertEntry; @@ -30,6 +29,7 @@ import net.sf.jabref.gui.util.PositionWindow; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.layout.CellConstraints; diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java index 88f683f1ff7e..97cf3d07f613 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java @@ -24,7 +24,6 @@ import javax.swing.JOptionPane; import javax.swing.JSeparator; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableChangeType; @@ -34,6 +33,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.layout.CellConstraints; diff --git a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java index 522b4baaf910..c59727628b2b 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java @@ -49,7 +49,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.external.UnknownExternalFileType; @@ -66,6 +65,7 @@ import net.sf.jabref.logic.openoffice.StyleLoader; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; diff --git a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java index 73eb5c7a1804..161de377a61c 100644 --- a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java +++ b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java @@ -110,7 +110,6 @@ import javax.swing.text.StyledDocument; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.ClipBoardManager; import net.sf.jabref.gui.EntryMarker; import net.sf.jabref.gui.FileDialogs; @@ -131,6 +130,7 @@ import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java index 1681cfdf8f19..c9b146bfc03a 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java @@ -26,13 +26,13 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.remote.JabRefMessageHandler; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.remote.RemotePreferences; import net.sf.jabref.logic.remote.RemoteUtil; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java index 26248ffc87db..554f0b24b0ac 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/AppearancePrefsTab.java @@ -32,10 +32,10 @@ import javax.swing.JTextField; import javax.swing.UIManager; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/ColorSetupPanel.java b/src/main/java/net/sf/jabref/gui/preftabs/ColorSetupPanel.java index 2e9e706b14af..15e891ae3f5c 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/ColorSetupPanel.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/ColorSetupPanel.java @@ -32,8 +32,8 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java index 51e3d897d5d5..80611ec61bd2 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/EntryEditorPrefsTab.java @@ -28,13 +28,13 @@ import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.keyboard.EmacsKeyBindings; import net.sf.jabref.logic.autocompleter.AutoCompleteFirstNameMode; import net.sf.jabref.logic.autocompleter.AutoCompletePreferences; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.CellConstraints; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java b/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java index a33649df0e40..f3af975ad094 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/ExternalTab.java @@ -32,13 +32,13 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileTypeEditor; import net.sf.jabref.external.push.PushToApplication; import net.sf.jabref.external.push.PushToApplicationButton; import net.sf.jabref.external.push.PushToApplications; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileSortTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileSortTab.java index b0091acd91e0..9ad7bf9b2c0f 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileSortTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileSortTab.java @@ -24,10 +24,10 @@ import javax.swing.JPanel; import javax.swing.JRadioButton; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.SaveOrderConfigDisplay; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index 8ba24b05a2b7..444ad9a57ae6 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -32,12 +32,12 @@ import javax.swing.SpinnerNumberModel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java b/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java index de24015ad887..b8fbb4bc154e 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java @@ -33,12 +33,12 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java index 73024114d120..8331d5c95b8c 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/GroupsPrefsTab.java @@ -25,8 +25,8 @@ import javax.swing.JPanel; import javax.swing.JTextField; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java index 29e15a175229..db2aec0e2e33 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/ImportSettingsTab.java @@ -29,9 +29,9 @@ import javax.swing.JRadioButton; import javax.swing.JTextField; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.pdfimport.ImportDialog; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java b/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java index 0aa5347ec6da..ba31351b58a0 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/LabelPatternPrefTab.java @@ -25,12 +25,12 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.labelpattern.LabelPatternPanel; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.GlobalLabelPattern; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java b/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java index 5359d5da8c1e..6cf2b967b3e2 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java @@ -35,13 +35,13 @@ import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.OSXCompatibleToolbar; import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.format.NameFormatter; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/NetworkTab.java b/src/main/java/net/sf/jabref/gui/preftabs/NetworkTab.java index 1f2917448891..9e2542f7a464 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/NetworkTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/NetworkTab.java @@ -26,10 +26,10 @@ import javax.swing.JPasswordField; import javax.swing.JTextField; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.ProxyPreferences; import net.sf.jabref.logic.net.ProxyRegisterer; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java index 7cf910aa5cba..c3b33ac699e7 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java @@ -38,9 +38,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefException; -import net.sf.jabref.JabRefPreferences; -import net.sf.jabref.JabRefPreferencesFilter; -import net.sf.jabref.JabRefPreferencesFilterDialog; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.JabRefFrame; @@ -48,6 +45,8 @@ import net.sf.jabref.gui.maintable.MainTable; import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferencesFilter; import com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.logging.Log; @@ -208,7 +207,7 @@ public PreferencesDialog(JabRefFrame parent) { }); showPreferences.addActionListener( - e -> new JabRefPreferencesFilterDialog(new JabRefPreferencesFilter(Globals.prefs), frame) + e -> new PreferencesFilterDialog(new JabRefPreferencesFilter(Globals.prefs), frame) .setVisible(true)); resetPreferences.addActionListener(e -> { if (JOptionPane.showConfirmDialog(PreferencesDialog.this, diff --git a/src/main/java/net/sf/jabref/JabRefPreferencesFilterDialog.java b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesFilterDialog.java similarity index 94% rename from src/main/java/net/sf/jabref/JabRefPreferencesFilterDialog.java rename to src/main/java/net/sf/jabref/gui/preftabs/PreferencesFilterDialog.java index a5e8e328f7f3..aacb9ae6e82c 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferencesFilterDialog.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesFilterDialog.java @@ -1,4 +1,4 @@ -package net.sf.jabref; +package net.sf.jabref.gui.preftabs; import java.awt.BorderLayout; import java.awt.Dimension; @@ -16,8 +16,9 @@ import net.sf.jabref.gui.WrapLayout; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferencesFilter; -public class JabRefPreferencesFilterDialog extends JDialog { +class PreferencesFilterDialog extends JDialog { private final JabRefPreferencesFilter preferencesFilter; @@ -25,7 +26,7 @@ public class JabRefPreferencesFilterDialog extends JDialog { private final JCheckBox showOnlyDeviatingPreferenceOptions; private final JLabel count; - public JabRefPreferencesFilterDialog(JabRefPreferencesFilter preferencesFilter, JFrame frame) { + public PreferencesFilterDialog(JabRefPreferencesFilter preferencesFilter, JFrame frame) { super(frame, true); // is modal this.preferencesFilter = Objects.requireNonNull(preferencesFilter); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java index ada75395d5a2..8c0a7cb4a625 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java @@ -29,11 +29,11 @@ import javax.swing.JTextArea; import javax.swing.SwingConstants; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.PreviewPanel; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java index 444beb55b0dd..f93b80d7f8f6 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java @@ -45,7 +45,6 @@ import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.gui.BasePanel; @@ -57,6 +56,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibtexSingleField; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; import com.jgoodies.forms.builder.DefaultFormBuilder; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java index 6aed10a300a5..bf70ae85306e 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java @@ -31,10 +31,10 @@ import javax.swing.JTable; import javax.swing.JTextField; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/XmpPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/XmpPrefsTab.java index 213e3578b53e..f18eaf844ea9 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/XmpPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/XmpPrefsTab.java @@ -37,10 +37,10 @@ import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.OSXCompatibleToolbar; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/gui/renderer/IncompleteRenderer.java b/src/main/java/net/sf/jabref/gui/renderer/IncompleteRenderer.java index 8d6312f32529..41522482e842 100644 --- a/src/main/java/net/sf/jabref/gui/renderer/IncompleteRenderer.java +++ b/src/main/java/net/sf/jabref/gui/renderer/IncompleteRenderer.java @@ -1,8 +1,8 @@ package net.sf.jabref.gui.renderer; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; public class IncompleteRenderer extends GeneralRenderer { diff --git a/src/main/java/net/sf/jabref/gui/search/SearchBar.java b/src/main/java/net/sf/jabref/gui/search/SearchBar.java index f5d3aceaf9f8..5cde5ab7df3b 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchBar.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchBar.java @@ -33,7 +33,6 @@ import javax.swing.JToolBar; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.OSXCompatibleToolbar; @@ -50,6 +49,7 @@ import net.sf.jabref.logic.search.SearchQueryHighlightObservable; import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java index 6a26648ab682..2d13727bc45f 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java @@ -47,7 +47,6 @@ import javax.swing.table.TableColumnModel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.ExternalFileMenuItem; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileListEntry; @@ -69,6 +68,7 @@ import net.sf.jabref.model.entry.EntryUtil; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; diff --git a/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java b/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java index dbbcad678882..d9f33eeda68c 100644 --- a/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java +++ b/src/main/java/net/sf/jabref/gui/worker/MarkEntriesAction.java @@ -22,13 +22,13 @@ import javax.swing.JMenuItem; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryMarker; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java b/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java index 76cd03428cd2..5f93c7ea2ee8 100644 --- a/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java +++ b/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java @@ -24,7 +24,6 @@ import java.util.ArrayList; import java.util.List; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.desktop.JabRefDesktop; @@ -33,6 +32,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java index bed6161798f6..8f83a6618a6f 100644 --- a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java @@ -25,7 +25,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileDialogs; @@ -47,6 +46,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java b/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java index a74e0ecb9a0f..9a47693b0bcd 100644 --- a/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java +++ b/src/main/java/net/sf/jabref/importer/AutosaveStartupPrompter.java @@ -25,12 +25,12 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.ParserResultWarningDialog; import net.sf.jabref.gui.exporter.AutoSaveManager; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; /** * Runnable task that prompts the user for what to do about files loaded at startup, diff --git a/src/main/java/net/sf/jabref/importer/CheckForNewEntryTypesAction.java b/src/main/java/net/sf/jabref/importer/CheckForNewEntryTypesAction.java index 658730880b52..c01a3dc06387 100644 --- a/src/main/java/net/sf/jabref/importer/CheckForNewEntryTypesAction.java +++ b/src/main/java/net/sf/jabref/importer/CheckForNewEntryTypesAction.java @@ -23,13 +23,13 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.preferences.JabRefPreferences; /** * This action checks whether any new custom entry types were loaded from this diff --git a/src/main/java/net/sf/jabref/importer/CustomImportList.java b/src/main/java/net/sf/jabref/importer/CustomImportList.java index 7a7146a8bd0b..51377785a132 100644 --- a/src/main/java/net/sf/jabref/importer/CustomImportList.java +++ b/src/main/java/net/sf/jabref/importer/CustomImportList.java @@ -31,7 +31,7 @@ import java.util.TreeSet; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java index a18e6c6d244b..3631ea391f06 100644 --- a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java @@ -44,7 +44,6 @@ import javax.swing.table.TableColumnModel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; @@ -53,6 +52,7 @@ import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/importer/ImportFormats.java b/src/main/java/net/sf/jabref/importer/ImportFormats.java index 8b713f6a0095..aaa40d9cb9c8 100644 --- a/src/main/java/net/sf/jabref/importer/ImportFormats.java +++ b/src/main/java/net/sf/jabref/importer/ImportFormats.java @@ -29,12 +29,12 @@ import javax.swing.filechooser.FileFilter; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java index 7d3d0483ce29..612253332657 100644 --- a/src/main/java/net/sf/jabref/importer/ImportMenuItem.java +++ b/src/main/java/net/sf/jabref/importer/ImportMenuItem.java @@ -31,7 +31,6 @@ import javax.swing.JOptionPane; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.EntryMarker; @@ -48,6 +47,7 @@ import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; +import net.sf.jabref.preferences.JabRefPreferences; /* * TODO: could separate the "menu item" functionality from the importing functionality diff --git a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java index 5c73a0c625bb..3662238e6fc4 100644 --- a/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/OpenDatabaseAction.java @@ -34,7 +34,6 @@ import net.sf.jabref.Defaults; import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileDialogs; @@ -53,6 +52,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; import org.apache.commons.logging.Log; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java index ab9b322df61e..6317ea3733c4 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java @@ -42,7 +42,6 @@ import javax.swing.JRadioButton; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FetcherPreviewDialog; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; @@ -54,6 +53,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java index b31fe6706980..cfe627127fcd 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java @@ -10,12 +10,12 @@ import java.util.concurrent.atomic.AtomicInteger; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; /** * Useful for checking out new algorithm improvements and thresholds. Not used inside the JabRef code itself. diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index fdd66cdf9572..9634b42bef56 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -10,7 +10,6 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -22,6 +21,7 @@ import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java index 9dfb60eadff5..1c77211087d4 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java @@ -26,7 +26,6 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -37,6 +36,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GeneralFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GeneralFetcher.java index 867b607dcc08..24b595f511da 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GeneralFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GeneralFetcher.java @@ -38,7 +38,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefExecutorService; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.FetcherPreviewDialog; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.ImportInspectionDialog; @@ -50,6 +49,7 @@ import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.OS; +import net.sf.jabref.preferences.JabRefPreferences; public class GeneralFetcher extends SidePaneComponent implements ActionListener { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index ff1f21963d34..7b5617d28d4e 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -36,7 +36,6 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -48,6 +47,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java index c926add43a32..0bb1b184f496 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java @@ -27,7 +27,6 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -36,6 +35,7 @@ import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java b/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java index c59f6fa70c82..855698424fef 100644 --- a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java +++ b/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java @@ -5,11 +5,11 @@ import java.util.List; import java.util.Optional; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.preferences.JabRefPreferences; public class CustomEntryTypesManager { diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java index eb65b43ccb75..c0694feae1e6 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java @@ -19,7 +19,7 @@ import java.util.Map; import java.util.Objects; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public class AutoCompletePreferences { diff --git a/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java index 825315e1c2f6..e52c0be187b4 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java @@ -20,8 +20,8 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.preferences.JabRefPreferences; /** * This class provides the reformatting needed when reading BibTeX fields formatted diff --git a/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java index a93df48ac424..347bdcbffe97 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java @@ -19,9 +19,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; /** * Currently the only implementation of net.sf.jabref.exporter.FieldFormatter diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java index e90c3f1c32b3..76a40d138b48 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java @@ -19,8 +19,8 @@ import java.util.Objects; import java.util.Set; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.exporter.FieldFormatterCleanups; +import net.sf.jabref.preferences.JabRefPreferences; public class CleanupPreset { diff --git a/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java b/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java index e0c84911e809..3008a677312d 100644 --- a/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java +++ b/src/main/java/net/sf/jabref/logic/config/SaveOrderConfig.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; /** * Stores the save order config from MetaData diff --git a/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java b/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java index f4af48464b3b..7b3ab7786a7a 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java +++ b/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java @@ -22,7 +22,7 @@ import java.util.TreeMap; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; diff --git a/src/main/java/net/sf/jabref/logic/exporter/FileSaveSession.java b/src/main/java/net/sf/jabref/logic/exporter/FileSaveSession.java index eee1a54b91af..c3a7d7846076 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/FileSaveSession.java +++ b/src/main/java/net/sf/jabref/logic/exporter/FileSaveSession.java @@ -23,10 +23,10 @@ import java.nio.file.Path; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileBasedLock; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java b/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java index 0d0b52db800f..d482609035a3 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java +++ b/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java @@ -3,8 +3,8 @@ import java.nio.charset.Charset; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.config.SaveOrderConfig; +import net.sf.jabref.preferences.JabRefPreferences; public class SavePreferences { diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java index 6f0a2d791801..875c4745de9f 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java @@ -21,11 +21,11 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.logic.util.strings.HTMLUnicodeConversionMaps; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java index b29bd7369d38..257df6c11148 100644 --- a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java @@ -23,7 +23,6 @@ import java.util.regex.PatternSyntaxException; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.strings.QuotedStringTokenizer; @@ -31,6 +30,7 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java b/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java index cb69c37f6855..8c5d30034bc0 100644 --- a/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java @@ -19,12 +19,12 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.strings.QuotedStringTokenizer; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java index b7ac873b82d0..a42cd306422c 100644 --- a/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java +++ b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java @@ -23,7 +23,7 @@ import java.util.Objects; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index 6e4c93f831e1..555bb8c6f6a9 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -27,7 +27,6 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.logic.formatter.casechanger.Word; import net.sf.jabref.logic.layout.format.RemoveLatexCommands; @@ -35,6 +34,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/net/ProxyPreferences.java b/src/main/java/net/sf/jabref/logic/net/ProxyPreferences.java index c7f2790f9786..78b2d31a4ebe 100644 --- a/src/main/java/net/sf/jabref/logic/net/ProxyPreferences.java +++ b/src/main/java/net/sf/jabref/logic/net/ProxyPreferences.java @@ -2,7 +2,7 @@ import java.util.Objects; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public class ProxyPreferences { diff --git a/src/main/java/net/sf/jabref/logic/openoffice/OpenOfficePreferences.java b/src/main/java/net/sf/jabref/logic/openoffice/OpenOfficePreferences.java index 4e6e5ba6bdde..01a1a0cf9666 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/OpenOfficePreferences.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/OpenOfficePreferences.java @@ -18,8 +18,8 @@ import java.io.File; import java.util.List; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; /** * The OpenOffice connection preferences are: diff --git a/src/main/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferences.java b/src/main/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferences.java index b87d53674c8f..7e27f8309272 100644 --- a/src/main/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferences.java +++ b/src/main/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferences.java @@ -19,7 +19,7 @@ import java.io.File; import java.util.Objects; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public class LastFocusedTabPreferences { diff --git a/src/main/java/net/sf/jabref/logic/remote/RemotePreferences.java b/src/main/java/net/sf/jabref/logic/remote/RemotePreferences.java index 6d83bfa418a3..b67e88d5e54c 100644 --- a/src/main/java/net/sf/jabref/logic/remote/RemotePreferences.java +++ b/src/main/java/net/sf/jabref/logic/remote/RemotePreferences.java @@ -1,6 +1,6 @@ package net.sf.jabref.logic.remote; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; /** * Place for handling the preferences for the remote communication diff --git a/src/main/java/net/sf/jabref/logic/util/UpdateField.java b/src/main/java/net/sf/jabref/logic/util/UpdateField.java index 8aa804559c92..ddd145b3af6d 100644 --- a/src/main/java/net/sf/jabref/logic/util/UpdateField.java +++ b/src/main/java/net/sf/jabref/logic/util/UpdateField.java @@ -4,11 +4,11 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.util.date.EasyDateFormat; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; public class UpdateField { diff --git a/src/main/java/net/sf/jabref/logic/util/VersionPreferences.java b/src/main/java/net/sf/jabref/logic/util/VersionPreferences.java index e23d22ca4115..a0001d336ce9 100644 --- a/src/main/java/net/sf/jabref/logic/util/VersionPreferences.java +++ b/src/main/java/net/sf/jabref/logic/util/VersionPreferences.java @@ -15,7 +15,7 @@ */ package net.sf.jabref.logic.util; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public class VersionPreferences { diff --git a/src/main/java/net/sf/jabref/logic/util/date/EasyDateFormat.java b/src/main/java/net/sf/jabref/logic/util/date/EasyDateFormat.java index a1a2c8b85d59..22e70f8c1792 100644 --- a/src/main/java/net/sf/jabref/logic/util/date/EasyDateFormat.java +++ b/src/main/java/net/sf/jabref/logic/util/date/EasyDateFormat.java @@ -4,7 +4,7 @@ import java.util.Date; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public class EasyDateFormat { diff --git a/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java b/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java index 9f6ff9338d72..f1de485b2c50 100644 --- a/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java +++ b/src/main/java/net/sf/jabref/logic/util/date/TimeStamp.java @@ -3,10 +3,10 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.util.UpdateField; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; public class TimeStamp { diff --git a/src/main/java/net/sf/jabref/logic/util/io/FileHistory.java b/src/main/java/net/sf/jabref/logic/util/io/FileHistory.java index e434566387d3..0acdc5d59515 100644 --- a/src/main/java/net/sf/jabref/logic/util/io/FileHistory.java +++ b/src/main/java/net/sf/jabref/logic/util/io/FileHistory.java @@ -19,7 +19,7 @@ import java.util.LinkedList; import java.util.List; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public class FileHistory { 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 09a380a9669f..14305f73f2da 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 @@ -38,7 +38,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.layout.LayoutHelper; @@ -47,6 +46,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java index 4219dc0bb871..0269a6706294 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java @@ -24,7 +24,6 @@ import java.util.Set; import java.util.TreeSet; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; @@ -32,6 +31,7 @@ import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.jempbox.xmp.XMPMetadata; import org.apache.jempbox.xmp.XMPSchema; diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index 4a764f9b4d9f..23fed90a703f 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -42,7 +42,6 @@ import javax.xml.transform.TransformerException; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.TypedBibEntry; @@ -55,6 +54,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; import net.sf.jabref.model.entry.MonthUtil; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java index 031c26914550..fb17366a9603 100644 --- a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java +++ b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java @@ -26,7 +26,6 @@ import javax.swing.JTextField; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; @@ -39,6 +38,7 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; diff --git a/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java b/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java index b040aeb2fdb1..01e7d669a0ca 100644 --- a/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java @@ -4,7 +4,7 @@ import java.util.Map; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public class PreferencesMigrations { diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 409ee00e7cca..b4a45122fabb 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -35,10 +35,10 @@ import java.util.TreeSet; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.event.FieldChangedEvent; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.base.Strings; import com.google.common.eventbus.EventBus; diff --git a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index f95f6c536f84..c584b1aee724 100644 --- a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -43,7 +43,7 @@ import java.util.Set; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; public class InternalBibtexFields { diff --git a/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java b/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java index ec620d283eb7..6c5d5133700d 100644 --- a/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java +++ b/src/main/java/net/sf/jabref/pdfimport/ImportDialog.java @@ -38,9 +38,9 @@ import javax.swing.WindowConstants; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.DefaultFormBuilder; diff --git a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java index c961bf6730af..818a41045762 100644 --- a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java +++ b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java @@ -26,7 +26,6 @@ import javax.swing.JOptionPane; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.external.DroppedFileHandler; import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.gui.BasePanel; @@ -50,6 +49,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/net/sf/jabref/HighlightMatchingGroupPreferences.java b/src/main/java/net/sf/jabref/preferences/HighlightMatchingGroupPreferences.java similarity index 96% rename from src/main/java/net/sf/jabref/HighlightMatchingGroupPreferences.java rename to src/main/java/net/sf/jabref/preferences/HighlightMatchingGroupPreferences.java index 55dbcb3b3978..62724c6f57a1 100644 --- a/src/main/java/net/sf/jabref/HighlightMatchingGroupPreferences.java +++ b/src/main/java/net/sf/jabref/preferences/HighlightMatchingGroupPreferences.java @@ -1,4 +1,4 @@ -package net.sf.jabref; +package net.sf.jabref.preferences; public class HighlightMatchingGroupPreferences { diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java similarity index 99% rename from src/main/java/net/sf/jabref/JabRefPreferences.java rename to src/main/java/net/sf/jabref/preferences/JabRefPreferences.java index 648b81f5ab6d..33868186da60 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java @@ -13,7 +13,7 @@ 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; +package net.sf.jabref.preferences; import java.awt.Color; import java.io.File; @@ -46,6 +46,8 @@ import javax.swing.JTable; import javax.swing.UIManager; +import net.sf.jabref.JabRefException; +import net.sf.jabref.JabRefMain; import net.sf.jabref.external.DroppedFileHandler; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; diff --git a/src/main/java/net/sf/jabref/JabRefPreferencesFilter.java b/src/main/java/net/sf/jabref/preferences/JabRefPreferencesFilter.java similarity index 98% rename from src/main/java/net/sf/jabref/JabRefPreferencesFilter.java rename to src/main/java/net/sf/jabref/preferences/JabRefPreferencesFilter.java index aac9f27555a9..1b451cddfbf2 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferencesFilter.java +++ b/src/main/java/net/sf/jabref/preferences/JabRefPreferencesFilter.java @@ -1,4 +1,4 @@ -package net.sf.jabref; +package net.sf.jabref.preferences; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/net/sf/jabref/sql/DBStringsPreferences.java b/src/main/java/net/sf/jabref/sql/DBStringsPreferences.java index 45763e5d2123..62d067b0add1 100644 --- a/src/main/java/net/sf/jabref/sql/DBStringsPreferences.java +++ b/src/main/java/net/sf/jabref/sql/DBStringsPreferences.java @@ -1,6 +1,6 @@ package net.sf.jabref.sql; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; public final class DBStringsPreferences { diff --git a/src/test/java/net/sf/jabref/BibDatabaseContextTest.java b/src/test/java/net/sf/jabref/BibDatabaseContextTest.java index e875a58a86f0..ae29817ac268 100644 --- a/src/test/java/net/sf/jabref/BibDatabaseContextTest.java +++ b/src/test/java/net/sf/jabref/BibDatabaseContextTest.java @@ -2,6 +2,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/FileBasedTestCase.java b/src/test/java/net/sf/jabref/FileBasedTestCase.java index b11520fddce2..90eeefb15afd 100644 --- a/src/test/java/net/sf/jabref/FileBasedTestCase.java +++ b/src/test/java/net/sf/jabref/FileBasedTestCase.java @@ -5,6 +5,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/JabRefPreferencesTest.java b/src/test/java/net/sf/jabref/JabRefPreferencesTest.java index 0c9d17bcc9d2..7476105e3362 100644 --- a/src/test/java/net/sf/jabref/JabRefPreferencesTest.java +++ b/src/test/java/net/sf/jabref/JabRefPreferencesTest.java @@ -3,6 +3,8 @@ import java.io.File; import java.nio.charset.StandardCharsets; +import net.sf.jabref.preferences.JabRefPreferences; + import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/MetaDataTest.java b/src/test/java/net/sf/jabref/MetaDataTest.java index a0c7d9450b50..2009840ccc41 100644 --- a/src/test/java/net/sf/jabref/MetaDataTest.java +++ b/src/test/java/net/sf/jabref/MetaDataTest.java @@ -7,6 +7,7 @@ import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.casechanger.LowerCaseFormatter; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/SearchQueryHighlightListenerTest.java b/src/test/java/net/sf/jabref/SearchQueryHighlightListenerTest.java index fbe3f2e094b7..d6ded4ea4a39 100644 --- a/src/test/java/net/sf/jabref/SearchQueryHighlightListenerTest.java +++ b/src/test/java/net/sf/jabref/SearchQueryHighlightListenerTest.java @@ -22,6 +22,7 @@ import javax.swing.text.Highlighter.Highlight; import net.sf.jabref.gui.fieldeditors.TextArea; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/cli/AuxCommandLineTest.java b/src/test/java/net/sf/jabref/cli/AuxCommandLineTest.java index 8d732d2d1273..7ee12e7891ff 100644 --- a/src/test/java/net/sf/jabref/cli/AuxCommandLineTest.java +++ b/src/test/java/net/sf/jabref/cli/AuxCommandLineTest.java @@ -8,10 +8,10 @@ import java.nio.file.Paths; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java b/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java index 9da81f6624ea..f68a6ba149b9 100644 --- a/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java +++ b/src/test/java/net/sf/jabref/external/RegExpFileSearchTests.java @@ -25,13 +25,13 @@ import java.util.Map; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.layout.format.NameFormatter; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java index 0665e71ce349..e8e5fef54ad6 100644 --- a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java +++ b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java @@ -3,13 +3,13 @@ import java.util.Collections; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.logic.groups.AllEntriesGroup; import net.sf.jabref.logic.groups.ExplicitGroup; import net.sf.jabref.logic.groups.GroupHierarchyType; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java b/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java index 000ad0e86fa1..860f1d9e0e98 100644 --- a/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java +++ b/src/test/java/net/sf/jabref/importer/DatabaseFileLookupTest.java @@ -8,10 +8,10 @@ import java.util.Collection; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java b/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java index 0e550c2640f7..d27cec2947d5 100644 --- a/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java +++ b/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java @@ -25,10 +25,10 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java b/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java index 8474962db44d..330276e0ab64 100644 --- a/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java +++ b/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java @@ -20,9 +20,9 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/ImportFormatReaderIntegrationTest.java b/src/test/java/net/sf/jabref/importer/ImportFormatReaderIntegrationTest.java index 58729fcfea0d..1d680c80f2da 100644 --- a/src/test/java/net/sf/jabref/importer/ImportFormatReaderIntegrationTest.java +++ b/src/test/java/net/sf/jabref/importer/ImportFormatReaderIntegrationTest.java @@ -8,7 +8,7 @@ import java.util.Collection; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java b/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java index 9c8c8e859727..da5a973a0880 100644 --- a/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java +++ b/src/test/java/net/sf/jabref/importer/ImportFormatReaderTestParameterless.java @@ -6,7 +6,7 @@ import java.nio.file.Paths; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java b/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java index 687dfef9285e..39039ac30496 100644 --- a/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java +++ b/src/test/java/net/sf/jabref/importer/OpenDatabaseActionTest.java @@ -10,9 +10,9 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java index da12344752a9..bfb14092c273 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java @@ -9,9 +9,9 @@ import javax.xml.parsers.ParserConfigurationException; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java index 4f069e9a6754..48b4eef84dc8 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTest.java @@ -12,7 +12,7 @@ import java.util.stream.Collectors; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java index fc2c81a704e7..98b2516b0719 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestFiles.java @@ -14,9 +14,9 @@ import java.util.stream.Collectors; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java index e75d2475136a..1948a4b80e1c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibTeXMLImporterTestTypes.java @@ -9,8 +9,8 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java index 086aeeccc857..82157935f2ff 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTest.java @@ -7,7 +7,7 @@ import java.util.Collections; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java index afc910ec2f0c..9260ed362562 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestFiles.java @@ -10,9 +10,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java index 95a70c5f8046..b609ceda646f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BiblioscapeImporterTestTypes.java @@ -9,8 +9,8 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java index 4e066e672065..a2a7d4e1e4fd 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java @@ -9,8 +9,8 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java index 29b0fef3e8ff..e862aa95f18c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java @@ -13,7 +13,6 @@ import java.util.Set; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.config.SaveOrderConfig; @@ -30,6 +29,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.BeforeClass; import org.junit.Ignore; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java index d714527e52a7..f04544b6c71d 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java @@ -13,8 +13,8 @@ import java.util.stream.Collectors; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java index 4c054737809b..d2bd6c3f96f6 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTestFiles.java @@ -14,8 +14,8 @@ import java.util.stream.Collectors; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index 9c409fdde315..6c04829241fc 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -12,8 +12,8 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java index f46fb9aaa137..661ca3b675af 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/FreeCiteImporterTest.java @@ -3,7 +3,7 @@ import java.util.Arrays; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java index 7b9880b05ea9..1ff1db2a5eb7 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/InspecImportTest.java @@ -12,9 +12,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java index 815220b2d0b8..21ed2bea6ee2 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java @@ -10,8 +10,8 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java index a4c47f078a72..2c4e170ed07c 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java @@ -12,7 +12,7 @@ import java.util.stream.Collectors; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java index f0ada4dbeb4c..2cf5d5e25f11 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java @@ -13,9 +13,9 @@ import java.util.stream.Collectors; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index 810efe8fc7b9..f1c69d61492f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -14,9 +14,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java index 54543f8df8c7..1941806d46f3 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTest.java @@ -11,8 +11,8 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java index 3b9c229fa40a..86bfb9c715ed 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MsBibImporterTestfiles.java @@ -10,9 +10,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index 35f1d8f6eacf..c7e003083949 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -11,9 +11,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java index 305cb6113828..e5222fec0b51 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfContentImporterTestFiles.java @@ -10,9 +10,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index 211dbd59de0d..e2063e0c37d2 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -9,9 +9,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java index f95685db9424..b2f8af5cc5b5 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTest.java @@ -7,7 +7,7 @@ import java.nio.file.Paths; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java index 508711c4bfda..c7a9d62d39d0 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RISImporterTestFiles.java @@ -10,9 +10,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java index 7bc2f9912f86..c36b556de416 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/RepecNepImporterTest.java @@ -11,9 +11,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java index 3cb41948bafa..d07f05af055a 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTest.java @@ -9,9 +9,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.bibtex.BibEntryAssert; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java index 3efd7b9ab907..70a292aab6d9 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/SilverPlatterImporterTestNotRecognized.java @@ -8,7 +8,7 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/auxparser/AuxParserTest.java b/src/test/java/net/sf/jabref/logic/auxparser/AuxParserTest.java index 3eb2bf76be7e..5dad950e38cf 100644 --- a/src/test/java/net/sf/jabref/logic/auxparser/AuxParserTest.java +++ b/src/test/java/net/sf/jabref/logic/auxparser/AuxParserTest.java @@ -9,10 +9,10 @@ import java.nio.file.Paths; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java index be74d915a9f8..e8fcbc0ca7f9 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java @@ -7,11 +7,11 @@ import java.util.Set; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.AfterClass; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java index 63f6c8bdd7f9..289adb157cdf 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java @@ -3,10 +3,10 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibLatexEntryTypes; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java index c12c6e0f675e..f9c7f82c3fb3 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java @@ -5,11 +5,11 @@ import java.util.stream.Collectors; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.CustomEntryType; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java b/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java index 40d076aafb05..47a8fd30d363 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java @@ -1,7 +1,7 @@ package net.sf.jabref.logic.bibtex; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java b/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java index 24e914c50629..815e2c14afea 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java @@ -1,7 +1,7 @@ package net.sf.jabref.logic.bibtex; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/logic/bst/TestVM.java b/src/test/java/net/sf/jabref/logic/bst/TestVM.java index a63da63f73b0..4b255aae464f 100644 --- a/src/test/java/net/sf/jabref/logic/bst/TestVM.java +++ b/src/test/java/net/sf/jabref/logic/bst/TestVM.java @@ -8,12 +8,12 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.bst.VM.BstEntry; import net.sf.jabref.logic.bst.VM.StackFunction; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.antlr.runtime.RecognitionException; import org.junit.Assert; diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index 30bc897ee927..8a12be0e5bdc 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -9,7 +9,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.logic.exporter.FieldFormatterCleanups; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; @@ -25,6 +24,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java index b48b79137e32..7e0e6100b1a7 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java @@ -6,12 +6,12 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; 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.model.entry.ParsedFileField; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Rule; diff --git a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java index f80dd8ed1aa1..5690d16efeb6 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java @@ -7,13 +7,13 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; 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.model.entry.ParsedFileField; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Rule; diff --git a/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java b/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java index f5cce9ba6c6c..aa597b1d4a46 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -11,7 +11,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; @@ -33,6 +32,7 @@ import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.base.Charsets; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java index 56c0a0137150..d180b377294d 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java @@ -10,11 +10,11 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.base.Charsets; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java b/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java index 16122e70dda0..2662eaddf5d9 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java @@ -6,7 +6,6 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; import net.sf.jabref.logic.formatter.IdentityFormatter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; @@ -14,6 +13,7 @@ import net.sf.jabref.logic.formatter.casechanger.LowerCaseFormatter; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java index 14749370112f..19fb08598f44 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java @@ -8,11 +8,11 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.base.Charsets; import org.junit.After; diff --git a/src/test/java/net/sf/jabref/logic/exporter/MSBibExportFormatTestFiles.java b/src/test/java/net/sf/jabref/logic/exporter/MSBibExportFormatTestFiles.java index b9ce27ac87f6..b6f767231444 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/MSBibExportFormatTestFiles.java +++ b/src/test/java/net/sf/jabref/logic/exporter/MSBibExportFormatTestFiles.java @@ -15,11 +15,11 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.importer.fileformat.BibtexImporter; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.base.Charsets; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/exporter/MsBibExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/MsBibExportFormatTest.java index 977541ffc1a7..dd1500a389d9 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/MsBibExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/MsBibExportFormatTest.java @@ -9,10 +9,10 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.base.Charsets; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java index bb3dbbec3964..442e9421f086 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/FormatterTest.java @@ -4,7 +4,6 @@ import java.util.Collection; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.formatter.bibtexfields.ClearFormatter; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToUnicodeFormatter; @@ -25,6 +24,7 @@ import net.sf.jabref.logic.formatter.casechanger.UpperCaseFormatter; import net.sf.jabref.logic.formatter.minifier.MinifyNameListFormatter; import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java index e9e3c3d25175..beede42e473f 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatterTest.java @@ -1,7 +1,7 @@ package net.sf.jabref.logic.formatter.bibtexfields; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java index f6ca840b1804..bbf9276a5464 100644 --- a/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java +++ b/src/test/java/net/sf/jabref/logic/formatter/bibtexfields/UnicodeConverterTest.java @@ -1,7 +1,7 @@ package net.sf.jabref.logic.formatter.bibtexfields; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java index 7e1ff8d0fad1..35f33e51da49 100644 --- a/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java @@ -1,11 +1,11 @@ package net.sf.jabref.logic.groups; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java index 8010eb44fccd..3b48d6869408 100644 --- a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java @@ -6,11 +6,11 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.search.matchers.AndMatcher; import net.sf.jabref.logic.search.matchers.OrMatcher; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/groups/GroupsUtilTest.java b/src/test/java/net/sf/jabref/logic/groups/GroupsUtilTest.java index 9e6a9b24a4e5..00bcff94b263 100644 --- a/src/test/java/net/sf/jabref/logic/groups/GroupsUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/GroupsUtilTest.java @@ -7,10 +7,10 @@ import java.util.Set; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java index d9e1ae6ac6f0..60d851edce7f 100644 --- a/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java @@ -1,8 +1,8 @@ package net.sf.jabref.logic.groups; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java index 74de0c7c2a82..29f731626394 100644 --- a/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/net/sf/jabref/logic/integrity/IntegrityCheckTest.java @@ -10,12 +10,12 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.MetaData; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Rule; diff --git a/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java b/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java index 6ba66c28daf2..b65d91872366 100644 --- a/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java +++ b/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java @@ -1,7 +1,7 @@ package net.sf.jabref.logic.journals; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/l10n/LocalizationTest.java b/src/test/java/net/sf/jabref/logic/l10n/LocalizationTest.java index 8a7e7f8ff163..154ba1f07a3c 100644 --- a/src/test/java/net/sf/jabref/logic/l10n/LocalizationTest.java +++ b/src/test/java/net/sf/jabref/logic/l10n/LocalizationTest.java @@ -2,7 +2,7 @@ import java.util.Locale; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java b/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java index 8c658a94ae78..e372e9a09ffb 100644 --- a/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/labelpattern/LabelPatternUtilTest.java @@ -1,10 +1,10 @@ package net.sf.jabref.logic.labelpattern; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java index 39602d0d654f..bbf289d027bc 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java @@ -6,9 +6,9 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java index c10db239cbd7..a25aa6797350 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java @@ -5,11 +5,11 @@ import java.util.Collection; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java b/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java index 798dbc15d29f..3c78f9c424c3 100644 --- a/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java @@ -1,8 +1,8 @@ package net.sf.jabref.logic.layout.format; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.layout.ParamLayoutFormatter; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java b/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java index 14c265251dbe..ffee836e282d 100644 --- a/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java +++ b/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java @@ -6,7 +6,7 @@ import java.nio.charset.StandardCharsets; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java index 0e9e6aac7eaf..65fa1cf5b069 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java @@ -15,7 +15,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefMain; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.importer.fileformat.ImportFormat; @@ -23,6 +22,7 @@ import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java index 9e2cfd984e13..d86bd968523a 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java @@ -9,8 +9,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefMain; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferencesTest.java b/src/test/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferencesTest.java index 06075edefd6e..3bca9ed98c36 100644 --- a/src/test/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferencesTest.java +++ b/src/test/java/net/sf/jabref/logic/preferences/LastFocusedTabPreferencesTest.java @@ -2,7 +2,7 @@ import java.io.File; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.AfterClass; import org.junit.BeforeClass; diff --git a/src/test/java/net/sf/jabref/logic/search/MatchesHighlighterTest.java b/src/test/java/net/sf/jabref/logic/search/MatchesHighlighterTest.java index 9ed5d22e5c63..fcb5595da9c1 100644 --- a/src/test/java/net/sf/jabref/logic/search/MatchesHighlighterTest.java +++ b/src/test/java/net/sf/jabref/logic/search/MatchesHighlighterTest.java @@ -6,7 +6,7 @@ import java.util.regex.Pattern; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/search/rules/ContainBasedSearchRuleTest.java b/src/test/java/net/sf/jabref/logic/search/rules/ContainBasedSearchRuleTest.java index 24118d868b4c..997ffb7bffc0 100644 --- a/src/test/java/net/sf/jabref/logic/search/rules/ContainBasedSearchRuleTest.java +++ b/src/test/java/net/sf/jabref/logic/search/rules/ContainBasedSearchRuleTest.java @@ -1,10 +1,10 @@ package net.sf.jabref.logic.search.rules; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/util/io/FileHistoryTest.java b/src/test/java/net/sf/jabref/logic/util/io/FileHistoryTest.java index 0cee5a77b186..a7809720eda2 100644 --- a/src/test/java/net/sf/jabref/logic/util/io/FileHistoryTest.java +++ b/src/test/java/net/sf/jabref/logic/util/io/FileHistoryTest.java @@ -2,7 +2,7 @@ import java.util.List; -import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java index 925f418fa4ed..b778f48a1d7b 100644 --- a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java @@ -6,9 +6,9 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java b/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java index 8a8557edff52..f0e5a1ac0e3b 100644 --- a/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/util/strings/StringUtilTest.java @@ -1,8 +1,8 @@ package net.sf.jabref.logic.util.strings; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.FileField; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java b/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java index fba6d7028fe8..b016bcfc203c 100644 --- a/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java +++ b/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java @@ -11,8 +11,8 @@ import net.sf.jabref.BibtexTestData; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.jempbox.impl.XMLUtil; import org.apache.jempbox.xmp.XMPMetadata; diff --git a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java index 95fbfbc4a6e1..de3bd4184749 100644 --- a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java @@ -27,7 +27,6 @@ import javax.xml.transform.TransformerException; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.bibtex.BibEntryWriter; @@ -37,6 +36,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.io.CharStreams; import org.apache.jempbox.xmp.XMPMetadata; diff --git a/src/test/java/net/sf/jabref/model/DuplicateCheckTest.java b/src/test/java/net/sf/jabref/model/DuplicateCheckTest.java index de703bbea623..acbc9b1bca4f 100644 --- a/src/test/java/net/sf/jabref/model/DuplicateCheckTest.java +++ b/src/test/java/net/sf/jabref/model/DuplicateCheckTest.java @@ -1,11 +1,11 @@ package net.sf.jabref.model; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java index 012cb5b8f3e9..f5136528adb7 100644 --- a/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java +++ b/src/test/java/net/sf/jabref/model/database/BibDatabaseTest.java @@ -7,13 +7,13 @@ import java.util.Collections; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.event.TestEventListener; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Rule; diff --git a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java index 51a4770b7887..0d2c76710283 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java @@ -8,9 +8,9 @@ import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.FieldChange; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; diff --git a/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java b/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java index bab7c73d1a8a..cd451c2c52b7 100644 --- a/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java +++ b/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java @@ -6,7 +6,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.groups.AllEntriesGroup; import net.sf.jabref.logic.groups.GroupHierarchyType; @@ -15,6 +14,7 @@ import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.sql.exporter.DatabaseExporter; import net.sf.jabref.sql.importer.DBImporterResult; import net.sf.jabref.sql.importer.DatabaseImporter; From 82b8f6e50aa8ffb2749a174805a08e1ed1a16419 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 20 Jul 2016 08:13:06 +0200 Subject: [PATCH 250/268] =?UTF-8?q?Replace=20getField=20with=20getFieldOpt?= =?UTF-8?q?ional=20in=20all=20of=20the=20tests=20and=20in=20som=E2=80=A6?= =?UTF-8?q?=20(#1591)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Replace getField with getFieldOptional in all of the tests and in some more code * Some more conversions --- .../sf/jabref/external/AttachFileAction.java | 2 +- .../jabref/external/FindFullTextAction.java | 6 +- .../sf/jabref/external/WriteXMPAction.java | 11 +- .../external/WriteXMPEntryEditorAction.java | 9 +- .../java/net/sf/jabref/gui/BasePanel.java | 26 +-- .../java/net/sf/jabref/gui/EntryMarker.java | 40 +++-- .../sf/jabref/gui/ImportInspectionDialog.java | 10 +- .../sf/jabref/gui/ReplaceStringDialog.java | 2 +- .../sf/jabref/gui/desktop/JabRefDesktop.java | 7 +- .../gui/entryeditor/EntryEditorTab.java | 4 +- .../gui/journals/UndoableAbbreviator.java | 2 +- .../gui/journals/UndoableUnabbreviator.java | 2 +- .../maintable/MainTableSelectionListener.java | 5 +- .../maintable/SpecialMainTableColumns.java | 4 +- .../sf/jabref/gui/menus/RightClickMenu.java | 2 +- .../gui/plaintextimport/TextInputDialog.java | 14 +- .../gui/search/SearchResultsDialog.java | 8 +- .../jabref/importer/DatabaseFileLookup.java | 3 +- .../jabref/importer/EntryFromFileCreator.java | 15 +- .../net/sf/jabref/importer/OAI2Handler.java | 6 +- .../sf/jabref/importer/fetcher/CrossRef.java | 26 +-- .../fetcher/CrossrefFetcherEvaluator.java | 2 +- .../fetcher/GoogleScholarFetcher.java | 6 +- .../importer/fetcher/ISBNtoBibTeXFetcher.java | 6 +- .../jabref/importer/fetcher/OAI2Fetcher.java | 3 +- .../importer/fileformat/BibtexParser.java | 2 +- .../importer/fileformat/CopacImporter.java | 2 +- .../importer/fileformat/FreeCiteImporter.java | 10 +- .../autocompleter/NameFieldAutoCompleter.java | 5 +- .../sf/jabref/logic/groups/GroupsUtil.java | 28 +-- .../jabref/logic/integrity/ISSNChecker.java | 2 +- .../net/sf/jabref/logic/util/UpdateField.java | 2 +- .../net/sf/jabref/logic/util/io/FileUtil.java | 10 +- .../net/sf/jabref/model/entry/BibEntry.java | 12 +- .../ConvertLegacyExplicitGroupsTest.java | 5 +- .../EntryFromFileCreatorManagerTest.java | 2 +- .../importer/EntryFromPDFCreatorTest.java | 5 +- .../importer/fetcher/GVKParserTest.java | 11 +- .../fetcher/OAI2HandlerFetcherTest.java | 52 +++--- .../fileformat/BibtexImporterTest.java | 74 ++++---- .../importer/fileformat/BibtexParserTest.java | 138 +++++++-------- .../fileformat/EndnoteImporterTest.java | 69 ++++---- .../importer/fileformat/IsiImporterTest.java | 160 +++++++++--------- .../fileformat/JSONEntryParserTest.java | 29 ++-- .../fileformat/MedlinePlainImporterTest.java | 25 +-- .../importer/fileformat/OvidImporterTest.java | 63 +++---- .../fileformat/PdfXmpImporterTest.java | 9 +- .../logic/cleanup/CleanupWorkerTest.java | 46 ++--- .../logic/cleanup/MoveFilesCleanupTest.java | 10 +- .../logic/cleanup/RenamePdfCleanupTest.java | 13 +- .../exporter/FieldFormatterCleanupsTest.java | 18 +- .../sf/jabref/logic/util/UpdateFieldTest.java | 6 +- .../jabref/logic/xmp/XMPSchemaBibtexTest.java | 2 +- 53 files changed, 536 insertions(+), 495 deletions(-) diff --git a/src/main/java/net/sf/jabref/external/AttachFileAction.java b/src/main/java/net/sf/jabref/external/AttachFileAction.java index eb43b0533f9f..c81681396600 100644 --- a/src/main/java/net/sf/jabref/external/AttachFileAction.java +++ b/src/main/java/net/sf/jabref/external/AttachFileAction.java @@ -44,7 +44,7 @@ public void action() { String newVal = model.getStringRepresentation(); UndoableFieldChange ce = new UndoableFieldChange(entry, Globals.FILE_FIELD, - entry.getField(Globals.FILE_FIELD), newVal); + entry.getFieldOptional(Globals.FILE_FIELD).orElse(null), newVal); entry.setField(Globals.FILE_FIELD, newVal); panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); diff --git a/src/main/java/net/sf/jabref/external/FindFullTextAction.java b/src/main/java/net/sf/jabref/external/FindFullTextAction.java index e00758c6e4d0..d0ce54094dc6 100644 --- a/src/main/java/net/sf/jabref/external/FindFullTextAction.java +++ b/src/main/java/net/sf/jabref/external/FindFullTextAction.java @@ -80,11 +80,11 @@ public void update() { try { def.download(result.get(), file -> { FileListTableModel tm = new FileListTableModel(); - String oldValue = entry.getField(Globals.FILE_FIELD); - tm.setContent(oldValue); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); tm.addEntry(tm.getRowCount(), file); String newValue = tm.getStringRepresentation(); - UndoableFieldChange edit = new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue); + UndoableFieldChange edit = new UndoableFieldChange(entry, Globals.FILE_FIELD, + entry.getFieldOptional(Globals.FILE_FIELD).orElse(null), newValue); entry.setField(Globals.FILE_FIELD, newValue); basePanel.getUndoManager().addEdit(edit); basePanel.markBaseChanged(); diff --git a/src/main/java/net/sf/jabref/external/WriteXMPAction.java b/src/main/java/net/sf/jabref/external/WriteXMPAction.java index e031a12541ff..8864b53e3cec 100644 --- a/src/main/java/net/sf/jabref/external/WriteXMPAction.java +++ b/src/main/java/net/sf/jabref/external/WriteXMPAction.java @@ -133,15 +133,14 @@ public void run() { List files = new ArrayList<>(); // First check the (legacy) "pdf" field: - String pdf = entry.getField("pdf"); - List dirs = panel.getBibDatabaseContext().getFileDirectory("pdf"); - FileUtil.expandFilename(pdf, dirs).ifPresent(files::add); - + entry.getFieldOptional("pdf").ifPresent(pdf -> + FileUtil.expandFilename(pdf, panel.getBibDatabaseContext().getFileDirectory("pdf")) + .ifPresent(files::add)); // Then check the "file" field: - dirs = panel.getBibDatabaseContext().getFileDirectory(); + List dirs = panel.getBibDatabaseContext().getFileDirectory(); if (entry.hasField(Globals.FILE_FIELD)) { FileListTableModel tm = new FileListTableModel(); - tm.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); for (int j = 0; j < tm.getRowCount(); j++) { FileListEntry flEntry = tm.getEntry(j); if ((flEntry.type.isPresent()) && "pdf".equalsIgnoreCase(flEntry.type.get().getName())) { diff --git a/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java b/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java index 90bfff02a096..feca27d8c9ee 100644 --- a/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java +++ b/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java @@ -68,15 +68,14 @@ public void actionPerformed(ActionEvent actionEvent) { List files = new ArrayList<>(); // First check the (legacy) "pdf" field: - String pdf = entry.getField("pdf"); - List dirs = panel.getBibDatabaseContext().getFileDirectory("pdf"); - FileUtil.expandFilename(pdf, dirs).ifPresent(files::add); + entry.getFieldOptional("pdf").ifPresent(pdf -> FileUtil + .expandFilename(pdf, panel.getBibDatabaseContext().getFileDirectory("pdf")).ifPresent(files::add)); // Then check the "file" field: - dirs = panel.getBibDatabaseContext().getFileDirectory(); + List dirs = panel.getBibDatabaseContext().getFileDirectory(); if (entry.hasField(Globals.FILE_FIELD)) { FileListTableModel tm = new FileListTableModel(); - tm.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); for (int j = 0; j < tm.getRowCount(); j++) { FileListEntry flEntry = tm.getEntry(j); if ((flEntry.type.isPresent()) && "pdf".equalsIgnoreCase(flEntry.type.get().getName())) { diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 2a7e11a13a07..bf221b400852 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -1040,7 +1040,7 @@ private void openExternalFile() { return; } FileListTableModel tableModel = new FileListTableModel(); - tableModel.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tableModel::setContent); if (tableModel.getRowCount() == 0) { // content in bibtex field is not readable new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); @@ -2064,19 +2064,26 @@ private class OpenURLAction implements BaseAction { @Override public void action() { final List bes = mainTable.getSelectedEntries(); - String field = DOI_FIELD; if (bes.size() == 1) { - Object link = bes.get(0).getField(DOI_FIELD); + String field = DOI_FIELD; + Optional link = bes.get(0).getFieldOptional(DOI_FIELD); if (bes.get(0).hasField(URL_FIELD)) { - link = bes.get(0).getField(URL_FIELD); + link = bes.get(0).getFieldOptional(URL_FIELD); field = URL_FIELD; } - if (link == null) { + if (link.isPresent()) { + try { + JabRefDesktop.openExternalViewer(bibDatabaseContext, link.get(), field); + output(Localization.lang("External viewer called") + '.'); + } catch (IOException ex) { + output(Localization.lang("Error") + ": " + ex.getMessage()); + } + } else { // No URL or DOI found in the "url" and "doi" fields. // Look for web links in the "file" field as a fallback: FileListEntry entry = null; FileListTableModel tm = new FileListTableModel(); - tm.setContent(bes.get(0).getField(Globals.FILE_FIELD)); + bes.get(0).getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); for (int i = 0; i < tm.getRowCount(); i++) { FileListEntry flEntry = tm.getEntry(i); if (URL_FIELD.equalsIgnoreCase(flEntry.type.get().getName()) @@ -2097,13 +2104,6 @@ public void action() { LOGGER.info("Could not open link", e); } } - } else { - try { - JabRefDesktop.openExternalViewer(bibDatabaseContext, link.toString(), field); - output(Localization.lang("External viewer called") + '.'); - } catch (IOException ex) { - output(Localization.lang("Error") + ": " + ex.getMessage()); - } } } else { output(Localization.lang("This operation requires exactly one item to be selected.")); diff --git a/src/main/java/net/sf/jabref/gui/EntryMarker.java b/src/main/java/net/sf/jabref/gui/EntryMarker.java index cd8ce7987d05..ede302316eb2 100644 --- a/src/main/java/net/sf/jabref/gui/EntryMarker.java +++ b/src/main/java/net/sf/jabref/gui/EntryMarker.java @@ -44,18 +44,18 @@ public static void markEntry(BibEntry be, int markIncrement, boolean increment, int prevMarkLevel; String newValue = null; if (be.hasField(InternalBibtexFields.MARKED)) { - String s = be.getField(InternalBibtexFields.MARKED); - int index = s.indexOf(Globals.prefs.WRAPPED_USERNAME); + String markerString = be.getFieldOptional(InternalBibtexFields.MARKED).get(); + int index = markerString.indexOf(Globals.prefs.WRAPPED_USERNAME); if (index >= 0) { // Already marked 1 for this user. prevMarkLevel = 1; - newValue = s.substring(0, index) + s.substring(index + Globals.prefs.WRAPPED_USERNAME.length()) + Globals.prefs.WRAPPED_USERNAME.substring(0, Globals.prefs.WRAPPED_USERNAME.length() - 1) + ":" + (increment ? Math.min(MAX_MARKING_LEVEL, prevMarkLevel + markIncrement) : markIncrement) + "]"; + newValue = markerString.substring(0, index) + markerString.substring(index + Globals.prefs.WRAPPED_USERNAME.length()) + Globals.prefs.WRAPPED_USERNAME.substring(0, Globals.prefs.WRAPPED_USERNAME.length() - 1) + ":" + (increment ? Math.min(MAX_MARKING_LEVEL, prevMarkLevel + markIncrement) : markIncrement) + "]"; } else { - Matcher m = MARK_NUMBER_PATTERN.matcher(s); + Matcher m = MARK_NUMBER_PATTERN.matcher(markerString); if (m.find()) { try { prevMarkLevel = Integer.parseInt(m.group(1)); - newValue = s.substring(0, m.start(1)) + (increment ? Math.min(MAX_MARKING_LEVEL, prevMarkLevel + markIncrement) : markIncrement) + s.substring(m.end(1)); + newValue = markerString.substring(0, m.start(1)) + (increment ? Math.min(MAX_MARKING_LEVEL, prevMarkLevel + markIncrement) : markIncrement) + markerString.substring(m.end(1)); } catch (NumberFormatException ex) { // Do nothing. } @@ -66,7 +66,8 @@ public static void markEntry(BibEntry be, int markIncrement, boolean increment, newValue = Globals.prefs.WRAPPED_USERNAME.substring(0, Globals.prefs.WRAPPED_USERNAME.length() - 1) + ":" + markIncrement + "]"; } - ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, be.getField(InternalBibtexFields.MARKED), newValue)); + ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, + be.getFieldOptional(InternalBibtexFields.MARKED).orElse(null), newValue)); be.setField(InternalBibtexFields.MARKED, newValue); } @@ -75,35 +76,35 @@ public static void markEntry(BibEntry be, int markIncrement, boolean increment, */ public static void unmarkEntry(BibEntry be, boolean onlyMaxLevel, BibDatabase database, NamedCompound ce) { if (be.hasField(InternalBibtexFields.MARKED)) { - String s = be.getField(InternalBibtexFields.MARKED); - if ("0".equals(s)) { + String markerString = be.getFieldOptional(InternalBibtexFields.MARKED).get(); + if ("0".equals(markerString)) { if (!onlyMaxLevel) { unmarkOldStyle(be, database, ce); } return; } String newValue = null; - int index = s.indexOf(Globals.prefs.WRAPPED_USERNAME); + int index = markerString.indexOf(Globals.prefs.WRAPPED_USERNAME); if (index >= 0) { // Marked 1 for this user. if (onlyMaxLevel) { return; } else { - newValue = s.substring(0, index) + s.substring(index + Globals.prefs.WRAPPED_USERNAME.length()); + newValue = markerString.substring(0, index) + markerString.substring(index + Globals.prefs.WRAPPED_USERNAME.length()); } } else { - Matcher m = MARK_NUMBER_PATTERN.matcher(s); + Matcher m = MARK_NUMBER_PATTERN.matcher(markerString); if (m.find()) { try { int prevMarkLevel = Integer.parseInt(m.group(1)); if (!onlyMaxLevel || (prevMarkLevel == MARK_COLOR_LEVELS)) { if (prevMarkLevel > 1) { - newValue = s.substring(0, m.start(1)) + s.substring(m.end(1)); + newValue = markerString.substring(0, m.start(1)) + markerString.substring(m.end(1)); } else { String toRemove = Globals.prefs.WRAPPED_USERNAME.substring(0, Globals.prefs.WRAPPED_USERNAME.length() - 1) + ":1]"; - index = s.indexOf(toRemove); + index = markerString.indexOf(toRemove); if (index >= 0) { - newValue = s.substring(0, index) + s.substring(index + toRemove.length()); + newValue = markerString.substring(0, index) + markerString.substring(index + toRemove.length()); } } } else { @@ -127,7 +128,8 @@ public static void unmarkEntry(BibEntry be, boolean onlyMaxLevel, BibDatabase da sb.append(s.substring(piv)); } String newVal = sb.length() > 0 ? sb.toString() : null;*/ - ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, be.getField(InternalBibtexFields.MARKED), newValue)); + ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, + be.getFieldOptional(InternalBibtexFields.MARKED).get(), newValue)); if (newValue == null) { be.clearField(InternalBibtexFields.MARKED); } else { @@ -161,10 +163,12 @@ private static void unmarkOldStyle(BibEntry be, BibDatabase database, NamedCompo } String newVal = sb.toString(); if (newVal.isEmpty()) { - ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, be.getField(InternalBibtexFields.MARKED), null)); + ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, + be.getFieldOptional(InternalBibtexFields.MARKED).orElse(null), null)); be.clearField(InternalBibtexFields.MARKED); } else { - ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, be.getField(InternalBibtexFields.MARKED), newVal)); + ce.addEdit(new UndoableFieldChange(be, InternalBibtexFields.MARKED, + be.getFieldOptional(InternalBibtexFields.MARKED).orElse(null), newVal)); be.setField(InternalBibtexFields.MARKED, newVal); } } @@ -173,7 +177,7 @@ public static int isMarked(BibEntry be) { if (!be.hasField(InternalBibtexFields.MARKED)) { return 0; } - String s = be.getField(InternalBibtexFields.MARKED); + String s = be.getFieldOptional(InternalBibtexFields.MARKED).get(); if ("0".equals(s)) { return 1; } diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 85e0ec273de2..563b05d814e4 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -907,7 +907,7 @@ public void mouseClicked(MouseEvent e) { if (col == FILE_COL) { if (entry.hasField(Globals.FILE_FIELD)) { FileListTableModel tableModel = new FileListTableModel(); - tableModel.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tableModel::setContent); if (tableModel.getRowCount() == 0) { return; } @@ -1129,7 +1129,7 @@ public void actionPerformed(ActionEvent event) { } BibEntry entry = selectionModel.getSelected().get(0); String result = JOptionPane.showInputDialog(ImportInspectionDialog.this, Localization.lang("Enter URL"), - entry.getField(URL_FIELD)); + entry.getFieldOptional(URL_FIELD).orElse("")); entries.getReadWriteLock().writeLock().lock(); try { if (result != null) { @@ -1425,7 +1425,7 @@ public Object getColumnValue(BibEntry entry, int i) { case FILE_COL: if (entry.hasField(Globals.FILE_FIELD)) { FileListTableModel model = new FileListTableModel(); - model.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(model::setContent); fileLabel.setToolTipText(model.getToolTipHTMLRepresentation()); if (model.getRowCount() > 0) { fileLabel.setIcon(model.getEntry(0).type.get().getIcon()); @@ -1436,7 +1436,7 @@ public Object getColumnValue(BibEntry entry, int i) { } case URL_COL: if (entry.hasField(URL_FIELD)) { - urlLabel.setToolTipText(entry.getField(URL_FIELD)); + urlLabel.setToolTipText(entry.getFieldOptional(URL_FIELD).orElse("")); return urlLabel; } else { return null; @@ -1449,7 +1449,7 @@ public Object getColumnValue(BibEntry entry, int i) { if (InternalBibtexFields.getFieldExtras(field).contains(FieldProperties.PERSON_NAMES)) { return entry.getFieldOptional(field).map(AuthorList::fixAuthorNatbib).orElse(""); } else { - return entry.getField(field); + return entry.getFieldOptional(field).orElse(null); } } } diff --git a/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java b/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java index 182d7c902f87..f2695a8e19e8 100644 --- a/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java +++ b/src/main/java/net/sf/jabref/gui/ReplaceStringDialog.java @@ -222,7 +222,7 @@ private int replaceField(BibEntry be, String fieldname, NamedCompound ce) { if (!be.hasField(fieldname)) { return 0; } - String txt = be.getField(fieldname); + String txt = be.getFieldOptional(fieldname).get(); StringBuilder sb = new StringBuilder(); int ind; int piv = 0; diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index d5c126bae2c3..7627609ffa36 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -228,8 +228,8 @@ public static boolean openExternalFileUnknown(JabRefFrame frame, BibEntry entry, // User wants to change the type of this link. // First get a model of all file links for this entry: FileListTableModel tModel = new FileListTableModel(); - String oldValue = entry.getField(Globals.FILE_FIELD); - tModel.setContent(oldValue); + Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + oldValue.ifPresent(tModel::setContent); FileListEntry flEntry = null; // Then find which one we are looking at: for (int i = 0; i < tModel.getRowCount(); i++) { @@ -249,7 +249,8 @@ public static boolean openExternalFileUnknown(JabRefFrame frame, BibEntry entry, if (editor.okPressed()) { // Store the changes and add an undo edit: String newValue = tModel.getStringRepresentation(); - UndoableFieldChange ce = new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue); + UndoableFieldChange ce = new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue.orElse(null), + newValue); entry.setField(Globals.FILE_FIELD, newValue); frame.getCurrentBasePanel().getUndoManager().addEdit(ce); frame.getCurrentBasePanel().markBaseChanged(); diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java index f170f65968f5..e77b8bc0da07 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java @@ -26,7 +26,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -225,8 +224,7 @@ private boolean isFieldModified(FieldEditor fieldEditor) { if (text.isEmpty()) { return getEntry().hasField(fieldEditor.getFieldName()); } else { - String entryValue = getEntry().getField(fieldEditor.getFieldName()); - return !Objects.equals(entryValue, text); + return !Optional.of(text).equals(getEntry().getFieldOptional(fieldEditor.getFieldName())); } } diff --git a/src/main/java/net/sf/jabref/gui/journals/UndoableAbbreviator.java b/src/main/java/net/sf/jabref/gui/journals/UndoableAbbreviator.java index 3f3d16cb6dfc..29956e913da7 100644 --- a/src/main/java/net/sf/jabref/gui/journals/UndoableAbbreviator.java +++ b/src/main/java/net/sf/jabref/gui/journals/UndoableAbbreviator.java @@ -32,7 +32,7 @@ public boolean abbreviate(BibDatabase database, BibEntry entry, String fieldName if (!entry.hasField(fieldName)) { return false; } - String text = entry.getField(fieldName); + String text = entry.getFieldOptional(fieldName).get(); String origText = text; if (database != null) { text = database.resolveForStrings(text); diff --git a/src/main/java/net/sf/jabref/gui/journals/UndoableUnabbreviator.java b/src/main/java/net/sf/jabref/gui/journals/UndoableUnabbreviator.java index 75b81ae06916..f3f675a5dfb9 100644 --- a/src/main/java/net/sf/jabref/gui/journals/UndoableUnabbreviator.java +++ b/src/main/java/net/sf/jabref/gui/journals/UndoableUnabbreviator.java @@ -29,7 +29,7 @@ public boolean unabbreviate(BibDatabase database, BibEntry entry, String fieldNa if (!entry.hasField(fieldName)) { return false; } - String text = entry.getField(fieldName); + String text = entry.getFieldOptional(fieldName).get(); String origText = text; if (database != null) { text = database.resolveForStrings(text); diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index 9bc835e31486..a7cc08f86c70 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -292,7 +292,7 @@ public void mouseClicked(MouseEvent e) { for (String fieldName : fieldNames) { // Check if field is present, if not skip this field if (entry.hasField(fieldName)) { - String link = entry.getField(fieldName); + String link = entry.getFieldOptional(fieldName).get(); // See if this is a simple file link field, or if it is a file-list // field that can specify a list of links: @@ -402,9 +402,8 @@ private void showIconRightClickMenu(MouseEvent e, int row, MainTableColumn colum for(String field : column.getBibtexFields()) { if (Globals.FILE_FIELD.equals(field)) { // We use a FileListTableModel to parse the field content: - String fileFieldContent = entry.getField(field); FileListTableModel fileList = new FileListTableModel(); - fileList.setContent(fileFieldContent); + entry.getFieldOptional(field).ifPresent(fileList::setContent); for (int i = 0; i < fileList.getRowCount(); i++) { FileListEntry flEntry = fileList.getEntry(i); if (column.isFileFilter() diff --git a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java index 727c4718d661..7ce3a75e92dc 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java +++ b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java @@ -106,7 +106,7 @@ public Object getColumnValue(BibEntry entry) { public Object getColumnValue(BibEntry entry) { // We use a FileListTableModel to parse the field content: FileListTableModel fileList = new FileListTableModel(); - fileList.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileList::setContent); if (fileList.getRowCount() > 1) { return new JLabel(IconTheme.JabRefIcon.FILE_MULTIPLE.getSmallIcon()); } else if (fileList.getRowCount() == 1) { @@ -185,7 +185,7 @@ public Object getColumnValue(BibEntry entry) { boolean iconFound = false; JLabel iconLabel = null; FileListTableModel fileList = new FileListTableModel(); - fileList.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileList::setContent); for (int i = 0; i < fileList.getRowCount(); i++) { if ((fileList.getEntry(i).type.isPresent()) && externalFileTypeName.equalsIgnoreCase(fileList.getEntry(i).type.get().getName())) { diff --git a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java index 111aab887eb2..28c6dab4b9e6 100644 --- a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java @@ -280,7 +280,7 @@ private Icon getFileIconForSelectedEntry() { if (panel.getMainTable().getSelectedRowCount() == 1) { BibEntry entry = panel.getMainTable().getSelected().get(0); if(entry.hasField(Globals.FILE_FIELD)) { - JLabel label = FileListTableModel.getFirstLabel(entry.getField(Globals.FILE_FIELD)); + JLabel label = FileListTableModel.getFirstLabel(entry.getFieldOptional(Globals.FILE_FIELD).get()); if (label != null) { return label.getIcon(); } diff --git a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java index 161de377a61c..d324fdc27093 100644 --- a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java +++ b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java @@ -467,22 +467,22 @@ private void insertTextForTag(boolean overrideField) { markedTextStore.appendPosition(fieldName, selectionStart, selectionEnd); // get old text from BibTeX tag - String old = entry.getField(fieldName); + Optional old = entry.getFieldOptional(fieldName); // merge old and selected text - if (old == null) { - // "null"+"txt" Strings forbidden - entry.setField(fieldName, txt); - } else { + if (old.isPresent()) { // insert a new name with an additional "and" if (InternalBibtexFields.getFieldExtras(fieldName).contains(FieldProperties.PERSON_NAMES)) { - entry.setField(fieldName, old + " and " + txt); + entry.setField(fieldName, old.get() + " and " + txt); } else if ("keywords".equals(fieldName)) { // Add keyword entry.addKeyword(txt); } else { - entry.setField(fieldName, old + txt); + entry.setField(fieldName, old.get() + txt); } + } else { + // "null"+"txt" Strings forbidden + entry.setField(fieldName, txt); } } // make the new data in BibTeX source code visible diff --git a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java index 2d13727bc45f..ea5a5e5c2267 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java @@ -348,7 +348,7 @@ public void mouseClicked(MouseEvent e) { case FILE_COL: if (entry.hasField(Globals.FILE_FIELD)) { FileListTableModel tableModel = new FileListTableModel(); - tableModel.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tableModel::setContent); if (tableModel.getRowCount() == 0) { return; } @@ -388,7 +388,7 @@ public void processPopupTrigger(MouseEvent e) { if (col == FILE_COL) { // We use a FileListTableModel to parse the field content: FileListTableModel fileList = new FileListTableModel(); - fileList.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileList::setContent); // If there are one or more links, open the first one: for (int i = 0; i < fileList.getRowCount(); i++) { FileListEntry flEntry = fileList.getEntry(i); @@ -458,7 +458,7 @@ public Object getColumnValue(BibEntry entry, int column) { case FILE_COL: if (entry.hasField(Globals.FILE_FIELD)) { FileListTableModel tmpModel = new FileListTableModel(); - tmpModel.setContent(entry.getField(Globals.FILE_FIELD)); + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tmpModel::setContent); fileLabel.setToolTipText(tmpModel.getToolTipHTMLRepresentation()); if (tmpModel.getRowCount() > 0) { if (tmpModel.getEntry(0).type.isPresent()) { @@ -473,7 +473,7 @@ public Object getColumnValue(BibEntry entry, int column) { } case URL_COL: if (entry.hasField("url")) { - urlLabel.setToolTipText(entry.getField("url")); + urlLabel.setToolTipText(entry.getFieldOptional("url").get()); return urlLabel; } else { return null; diff --git a/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java b/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java index 3167b07d3ca4..88ac36c398a3 100644 --- a/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java +++ b/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java @@ -80,8 +80,7 @@ public boolean lookupDatabase(File file) { private List parseFileField(BibEntry entry) { Objects.requireNonNull(entry); - String fileField = entry.getField(Globals.FILE_FIELD); - List entries = FileField.parse(fileField); + List entries = FileField.parse(entry.getFieldOptional(Globals.FILE_FIELD).orElse(null)); List fileLinks = new ArrayList<>(); for (ParsedFileField field : entries) { diff --git a/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java b/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java index d7d74dc20cc0..f36d7a80cef0 100644 --- a/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java +++ b/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java @@ -169,15 +169,14 @@ protected void appendToField(BibEntry entry, String field, String value) { if ((value == null) || value.isEmpty()) { return; } - String oVal = entry.getField(field); - if (oVal == null) { - entry.setField(field, value); - } else { + Optional oVal = entry.getFieldOptional(field); + if (oVal.isPresent()) { // TODO: find Jabref constant for delimter - if (!oVal.contains(value)) { - entry.setField(field, oVal + "," + value); + if (!oVal.get().contains(value)) { + entry.setField(field, oVal.get() + "," + value); } - + } else { + entry.setField(field, value); } } @@ -191,7 +190,7 @@ protected void addEntrysToEntry(BibEntry entry, List entrys) { protected void addEntryDataToEntry(BibEntry entry, BibEntry e) { for (String field : e.getFieldNames()) { - appendToField(entry, field, e.getField(field)); + e.getFieldOptional(field).ifPresent(fieldContent -> appendToField(entry, field, fieldContent)); } } diff --git a/src/main/java/net/sf/jabref/importer/OAI2Handler.java b/src/main/java/net/sf/jabref/importer/OAI2Handler.java index d4f09f557970..101386ecb02a 100644 --- a/src/main/java/net/sf/jabref/importer/OAI2Handler.java +++ b/src/main/java/net/sf/jabref/importer/OAI2Handler.java @@ -15,6 +15,8 @@ */ package net.sf.jabref.importer; +import java.util.Optional; + import net.sf.jabref.model.entry.BibEntry; import org.xml.sax.Attributes; @@ -90,8 +92,8 @@ public void endElement(String uri, String localName, String qualifiedName) throw pages = pages.replace(" ", ""); entry.setField("pages", pages); } else if ("datestamp".equals(qualifiedName)) { - String year = entry.getField("year"); - if ((year == null) || year.isEmpty()) { + Optional year = entry.getFieldOptional("year"); + if (!year.isPresent() || year.get().isEmpty()) { entry.setField("year", content.replaceFirst("-.*", "")); } } else if ("title".equals(qualifiedName)) { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java index f539c9a3f878..da6ef06683c9 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java @@ -37,13 +37,13 @@ public static Optional findDOI(BibEntry entry) { Optional doi = Optional.empty(); // title is minimum requirement - String title = entry.getField("title"); + Optional title = entry.getFieldOptional("title"); - if ((title == null) || title.isEmpty()) { + if (!title.isPresent() || title.get().isEmpty()) { return doi; } - String query = enhanceQuery(title, entry); + String query = enhanceQuery(title.get(), entry); try { HttpResponse response = Unirest.get(API_URL + "/works") @@ -55,7 +55,7 @@ public static Optional findDOI(BibEntry entry) { // quality check if (checkValidity(entry, items)) { String dataDOI = items.getJSONObject(0).getString("DOI"); - LOGGER.debug("DOI " + dataDOI + " for " + title + " found."); + LOGGER.debug("DOI " + dataDOI + " for " + title.get() + " found."); return DOI.build(dataDOI); } } catch (UnirestException e) { @@ -67,16 +67,18 @@ public static Optional findDOI(BibEntry entry) { private static String enhanceQuery(String query, BibEntry entry) { StringBuilder enhancedQuery = new StringBuilder(query); // author - String author = entry.getField("author"); - if ((author != null) && !author.isEmpty()) { - enhancedQuery.append('+').append(author); - } + entry.getFieldOptional("author").ifPresent(author -> { + if (!author.isEmpty()) { + enhancedQuery.append('+').append(author); + } + }); // year - String year = entry.getField("year"); - if ((year != null) && !year.isEmpty()) { - enhancedQuery.append('+').append(year); - } + entry.getFieldOptional("year").ifPresent(year -> { + if (!year.isEmpty()) { + enhancedQuery.append('+').append(year); + } + }); return enhancedQuery.toString(); } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java index cfe627127fcd..843b1dee3fce 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws IOException, InterruptedException @Override public void run() { - Optional origDOI = DOI.build(entry.getField("doi")); + Optional origDOI = entry.getFieldOptional("doi").flatMap(DOI::build); if (origDOI.isPresent()) { dois.incrementAndGet(); Optional crossrefDOI = CrossRef.findDOI(entry); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java index e546ec37598d..6f22e69a30dd 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java @@ -283,14 +283,12 @@ private BibEntry downloadEntry(String link) throws IOException { // Clean up some remaining HTML code from Elsevier(?) papers // Search for: Poincare algebra // to see an example - String title = entry.getField("title"); - if (title != null) { + entry.getFieldOptional("title").ifPresent(title -> { String newtitle = title.replaceAll("<.?i>([^<]*)", "$1"); if (!newtitle.equals(title)) { entry.setField("title", newtitle); } - } - + }); return entry; } else if (entries.isEmpty()) { LOGGER.warn("No entry found! (" + link + ")"); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java index 0bb1b184f496..3c9949d76bc3 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java @@ -90,8 +90,7 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint BibEntry entry = BibtexParser.singleFromString(bibtexString); if (entry != null) { // Optionally add curly brackets around key words to keep the case - String title = entry.getField("title"); - if (title != null) { + entry.getFieldOptional("title").ifPresent(title -> { // Unit formatting if (Globals.prefs.getBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH)) { title = unitsToLatexFormatter.format(title); @@ -102,8 +101,7 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint title = protectTermsFormatter.format(title); } entry.setField("title", title); - } - + }); inspector.addEntry(entry); return true; } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java index e59f19a5ba12..e3357fe1d0ba 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java @@ -201,7 +201,8 @@ public BibEntry importOai2Entry(String key) { /* Correct line breaks and spacing */ for (String name : be.getFieldNames()) { - be.setField(name, OAI2Fetcher.correctLineBreaks(be.getField(name))); + be.getFieldOptional(name) + .ifPresent(content -> be.setField(name, OAI2Fetcher.correctLineBreaks(content))); } if (fixedKey.matches("\\d\\d\\d\\d\\..*")) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 78da8c784195..253bf298601e 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -559,7 +559,7 @@ private void parseField(BibEntry entry) throws IOException { // it inconvenient // for users if JabRef didn't accept it. if (InternalBibtexFields.getFieldExtras(key).contains(FieldProperties.PERSON_NAMES)) { - entry.setField(key, entry.getField(key) + " and " + content); + entry.setField(key, entry.getFieldOptional(key).get() + " and " + content); } else if ("keywords".equals(key)) { //multiple keywords fields should be combined to one entry.addKeyword(content); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java index d3e7d1b5e40a..2f906da50912 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java @@ -154,7 +154,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { private static void setOrAppend(BibEntry b, String field, String value, String separator) { if (b.hasField(field)) { - b.setField(field, b.getField(field) + separator + value); + b.setField(field, b.getFieldOptional(field).get() + separator + value); } else { b.setField(field, value); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index cd53d1226651..ae766615b393 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -198,12 +198,12 @@ public ParserResult importEntries(String text) { } if (noteSB.length() > 0) { - String note = e.getField("note"); - if (note == null) { - note = noteSB.toString(); - } else { + String note; + if (e.hasField("note")) { // "note" could have been set during the parsing as FreeCite also returns "note" - note = note.concat(Globals.NEWLINE).concat(noteSB.toString()); + note = e.getFieldOptional("note").get().concat(Globals.NEWLINE).concat(noteSB.toString()); + } else { + note = noteSB.toString(); } e.setField("note", note); } diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/NameFieldAutoCompleter.java b/src/main/java/net/sf/jabref/logic/autocompleter/NameFieldAutoCompleter.java index 0aad08008722..aa172e158b54 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/NameFieldAutoCompleter.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/NameFieldAutoCompleter.java @@ -91,13 +91,12 @@ public void addBibtexEntry(BibEntry entry) { return; } for (String fieldName : fieldNames) { - if (entry.hasField(fieldName)) { - String fieldValue = entry.getField(fieldName); + entry.getFieldOptional(fieldName).ifPresent(fieldValue -> { AuthorList authorList = AuthorList.parse(fieldValue); for (Author author : authorList.getAuthors()) { handleAuthor(author); } - } + }); } } diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java b/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java index 55f3141178dc..8806531b2978 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupsUtil.java @@ -10,6 +10,7 @@ import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.EntryUtil; public class GroupsUtil { @@ -17,13 +18,12 @@ public static Set findDeliminatedWordsInField(BibDatabase db, String fie Set res = new TreeSet<>(); for (BibEntry be : db.getEntries()) { - if (be.hasField(field)) { - String fieldValue = be.getField(field).trim(); - StringTokenizer tok = new StringTokenizer(fieldValue, deliminator); + be.getFieldOptional(field).ifPresent(fieldValue -> { + StringTokenizer tok = new StringTokenizer(fieldValue.trim(), deliminator); while (tok.hasMoreTokens()) { - res.add(net.sf.jabref.model.entry.EntryUtil.capitalizeFirst(tok.nextToken().trim())); + res.add(EntryUtil.capitalizeFirst(tok.nextToken().trim())); } - } + }); } return res; } @@ -43,7 +43,7 @@ public static Set findAllWordsInField(BibDatabase db, String field, Stri be.getFieldOptional(field).ifPresent(o -> { StringTokenizer tok = new StringTokenizer(o, remove, false); while (tok.hasMoreTokens()) { - res.add(net.sf.jabref.model.entry.EntryUtil.capitalizeFirst(tok.nextToken().trim())); + res.add(EntryUtil.capitalizeFirst(tok.nextToken().trim())); } }); } @@ -61,14 +61,14 @@ public static Set findAuthorLastNames(BibDatabase db, List field Set res = new TreeSet<>(); for (BibEntry be : db.getEntries()) { for (String field : fields) { - String val = be.getField(field); - if ((val != null) && !val.isEmpty()) { - AuthorList al = AuthorList.parse(val); - res.addAll(al.getAuthors().stream().map(Author::getLast) - .filter(lastName -> ((lastName != null) && !lastName.isEmpty())) - .collect(Collectors.toList())); - } - + be.getFieldOptional(field).ifPresent(val -> { + if (!val.isEmpty()) { + AuthorList al = AuthorList.parse(val); + res.addAll(al.getAuthors().stream().map(Author::getLast) + .filter(lastName -> ((lastName != null) && !lastName.isEmpty())) + .collect(Collectors.toList())); + } + }); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java index c8cfc50e8305..7f075ba106a4 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java @@ -21,7 +21,7 @@ public List check(BibEntry entry) { } // Check that the ISSN is on the correct form - String issn = entry.getField("issn").trim(); + String issn = entry.getFieldOptional("issn").get().trim(); Matcher issnMatcher = ISSN_PATTERN.matcher(issn); if (!issnMatcher.matches()) { return Collections.singletonList( diff --git a/src/main/java/net/sf/jabref/logic/util/UpdateField.java b/src/main/java/net/sf/jabref/logic/util/UpdateField.java index ddd145b3af6d..e5a828644d39 100644 --- a/src/main/java/net/sf/jabref/logic/util/UpdateField.java +++ b/src/main/java/net/sf/jabref/logic/util/UpdateField.java @@ -53,7 +53,7 @@ public static Optional updateField(BibEntry be, String field, Strin String writtenValue = null; String oldValue = null; if (be.hasField(field)) { - oldValue = be.getField(field); + oldValue = be.getFieldOptional(field).get(); if ((newValue == null) || (oldValue.equals(newValue) && nullFieldIfValueIsTheSame)) { // If the new field value is null or the old and the new value are the same and flag is set // Clear the field 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 14305f73f2da..126d1d82a0fb 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 @@ -372,10 +372,12 @@ public static List getListOfLinkedFiles(List bes, List f List result = new ArrayList<>(); for (BibEntry entry : bes) { - List fileList = FileField.parse(entry.getField(Globals.FILE_FIELD)); - for (ParsedFileField file : fileList) { - expandFilename(file.getLink(), fileDirs).ifPresent(result::add); - } + entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileField -> { + List fileList = FileField.parse(fileField); + for (ParsedFileField file : fileList) { + expandFilename(file.getLink(), fileDirs).ifPresent(result::add); + } + }); } return result; diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index b4a45122fabb..9ac64bd51929 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -60,7 +60,7 @@ public class BibEntry implements Cloneable { /* * Map to store the words in every field */ - private Map> fieldsAsWords = new HashMap<>(); + private final Map> fieldsAsWords = new HashMap<>(); // Search and grouping status is stored in boolean fields for quick reference: private boolean searchHit; @@ -263,13 +263,13 @@ public Optional getFieldOrAlias(String name) { // Finally, handle dates if ("date".equals(name)) { - String year = getField("year"); - MonthUtil.Month month = MonthUtil.getMonth(getField("month")); - if (year != null) { + Optional year = getFieldOptional("year"); + if (year.isPresent()) { + MonthUtil.Month month = MonthUtil.getMonth(getFieldOptional("month").orElse("")); if (month.isValid()) { - return Optional.of(year + '-' + month.twoDigitNumber); + return Optional.of(year.get() + '-' + month.twoDigitNumber); } else { - return Optional.of(year); + return year; } } } diff --git a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java index e8e5fef54ad6..f5cd24a89c86 100644 --- a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java +++ b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.importer; import java.util.Collections; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; @@ -43,7 +44,7 @@ public void performActionWritesGroupMembershipInEntry() throws Exception { action.performAction(basePanel, parserResult); - assertEquals("TestGroup", entry.getField("groups")); + assertEquals(Optional.of("TestGroup"), entry.getFieldOptional("groups")); } @Test @@ -64,7 +65,7 @@ public void performActionWritesGroupMembershipInEntryForComplexGroupTree() throw action.performAction(basePanel, parserResult); - assertEquals("TestGroup", entry.getField("groups")); + assertEquals(Optional.of("TestGroup"), entry.getFieldOptional("groups")); } @Test diff --git a/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java b/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java index d27cec2947d5..0941d01c8e1b 100644 --- a/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java +++ b/src/test/java/net/sf/jabref/importer/EntryFromFileCreatorManagerTest.java @@ -81,7 +81,7 @@ public void testAddEntrysFromFiles() throws FileNotFoundException, IOException { boolean file1Found = false; boolean file2Found = false; for (BibEntry entry : database.getEntries()) { - String filesInfo = entry.getField("file"); + String filesInfo = entry.getFieldOptional("file").get(); if (filesInfo.contains(files.get(0).getName())) { file1Found = true; } diff --git a/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java b/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java index 330276e0ab64..8a494c571daa 100644 --- a/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java +++ b/src/test/java/net/sf/jabref/importer/EntryFromPDFCreatorTest.java @@ -63,8 +63,9 @@ public void testCreationOfEntryNoPDF() { public void testCreationOfEntryNotInDatabase() { Optional entry = entryCreator.createEntry(ImportDataTest.FILE_NOT_IN_DATABASE, false); Assert.assertTrue(entry.isPresent()); - Assert.assertTrue(entry.get().getField("file").endsWith(":PDF")); - Assert.assertEquals(ImportDataTest.FILE_NOT_IN_DATABASE.getName(), entry.get().getField("title")); + Assert.assertTrue(entry.get().getFieldOptional("file").get().endsWith(":PDF")); + Assert.assertEquals(Optional.of(ImportDataTest.FILE_NOT_IN_DATABASE.getName()), + entry.get().getFieldOptional("title")); } } \ No newline at end of file diff --git a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java index bfb14092c273..c29490b1dff7 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import javax.xml.parsers.ParserConfigurationException; @@ -64,19 +65,19 @@ public void subTitleTest() throws IOException, ParserConfigurationException, SAX Assert.assertEquals(5, entries.size()); BibEntry entry = entries.get(0); - Assert.assertEquals(null, entry.getField("subtitle")); + Assert.assertEquals(Optional.empty(), entry.getFieldOptional("subtitle")); entry = entries.get(1); - Assert.assertEquals("C", entry.getField("subtitle")); + Assert.assertEquals(Optional.of("C"), entry.getFieldOptional("subtitle")); entry = entries.get(2); - Assert.assertEquals("Word", entry.getField("subtitle")); + Assert.assertEquals(Optional.of("Word"), entry.getFieldOptional("subtitle")); entry = entries.get(3); - Assert.assertEquals("Word1 word2", entry.getField("subtitle")); + Assert.assertEquals(Optional.of("Word1 word2"), entry.getFieldOptional("subtitle")); entry = entries.get(4); - Assert.assertEquals("Word1 word2", entry.getField("subtitle")); + Assert.assertEquals(Optional.of("Word1 word2"), entry.getFieldOptional("subtitle")); } } } diff --git a/src/test/java/net/sf/jabref/importer/fetcher/OAI2HandlerFetcherTest.java b/src/test/java/net/sf/jabref/importer/fetcher/OAI2HandlerFetcherTest.java index bef6d7e21b65..e301479edfcb 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/OAI2HandlerFetcherTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/OAI2HandlerFetcherTest.java @@ -1,6 +1,7 @@ package net.sf.jabref.importer.fetcher; import java.io.IOException; +import java.util.Optional; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; @@ -55,22 +56,22 @@ public void testCorrectLineBreaks() { public void testParse() throws Throwable { try { saxParser.parse(this.getClass().getResourceAsStream("oai2.xml"), handler); - Assert.assertEquals("hep-ph/0408155", be.getField("eprint")); - Assert.assertEquals("G. F. Giudice and A. Riotto and A. Zaffaroni and J. López-Peña", - be.getField("author")); - Assert.assertEquals("Nucl.Phys. B", be.getField("journal")); - Assert.assertEquals("710", be.getField("volume")); - Assert.assertEquals("2005", be.getField("year")); - Assert.assertEquals("511-525", be.getField("pages")); + Assert.assertEquals(Optional.of("hep-ph/0408155"), be.getFieldOptional("eprint")); + Assert.assertEquals(Optional.of("G. F. Giudice and A. Riotto and A. Zaffaroni and J. López-Peña"), + be.getFieldOptional("author")); + Assert.assertEquals(Optional.of("Nucl.Phys. B"), be.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("710"), be.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("2005"), be.getFieldOptional("year")); + Assert.assertEquals(Optional.of("511-525"), be.getFieldOptional("pages")); // Citekey is only generated if the user says so in the import // inspection dialog. Assert.assertEquals(null, be.getCiteKey()); - Assert.assertEquals("Heavy Particles from Inflation", be.getField("title")); - Assert.assertNotNull(be.getField("abstract")); - Assert.assertEquals("23 pages", be.getField("comments")); - Assert.assertEquals("CERN-PH-TH/2004-151", be.getField("reportno")); + Assert.assertEquals(Optional.of("Heavy Particles from Inflation"), be.getFieldOptional("title")); + Assert.assertTrue(be.getFieldOptional("abstract").isPresent()); + Assert.assertEquals(Optional.of("23 pages"), be.getFieldOptional("comments")); + Assert.assertEquals(Optional.of("CERN-PH-TH/2004-151"), be.getFieldOptional("reportno")); } catch (SAXException e) { throw e.getException(); } @@ -80,7 +81,7 @@ public void testParse() throws Throwable { public void testOai22xml() throws SAXException, IOException { saxParser.parse(this.getClass().getResourceAsStream("oai22.xml"), handler); - Assert.assertEquals("2005", be.getField("year")); + Assert.assertEquals(Optional.of("2005"), be.getFieldOptional("year")); } @@ -88,7 +89,7 @@ public void testOai22xml() throws SAXException, IOException { public void testOai23xml() throws SAXException, IOException { saxParser.parse(this.getClass().getResourceAsStream("oai23.xml"), handler); - Assert.assertEquals("Javier López Peña and Gabriel Navarro", be.getField("author")); + Assert.assertEquals(Optional.of("Javier López Peña and Gabriel Navarro"), be.getFieldOptional("author")); } @@ -125,11 +126,11 @@ public void testOnline() throws InterruptedException { be = fetcher.importOai2Entry("math.RA/0612188"); Assert.assertNotNull(be); - Assert.assertEquals("math/0612188", be.getField("eprint")); - Assert.assertEquals("On the classification and properties of noncommutative duplicates", - be.getField("title")); - Assert.assertEquals("Javier López Peña and Gabriel Navarro", be.getField("author")); - Assert.assertEquals("2007", be.getField("year")); + Assert.assertEquals(Optional.of("math/0612188"), be.getFieldOptional("eprint")); + Assert.assertEquals(Optional.of("On the classification and properties of noncommutative duplicates"), + be.getFieldOptional("title")); + Assert.assertEquals(Optional.of("Javier López Peña and Gabriel Navarro"), be.getFieldOptional("author")); + Assert.assertEquals(Optional.of("2007"), be.getFieldOptional("year")); Thread.sleep(20000); } @@ -139,10 +140,11 @@ public void testOnline() throws InterruptedException { be = fetcher.importOai2Entry("astro-ph/0702080"); Assert.assertNotNull(be); - Assert.assertEquals("astro-ph/0702080", be.getField("eprint")); + Assert.assertEquals(Optional.of("astro-ph/0702080"), be.getFieldOptional("eprint")); Assert.assertEquals( - "Magnetized Hypermassive Neutron Star Collapse: a candidate central engine for short-hard GRBs", - be.getField("title")); + Optional.of( + "Magnetized Hypermassive Neutron Star Collapse: a candidate central engine for short-hard GRBs"), + be.getFieldOptional("title")); Thread.sleep(20000); } @@ -152,7 +154,7 @@ public void testOnline() throws InterruptedException { be = fetcher.importOai2Entry("math.QA/0601001"); Assert.assertNotNull(be); - Assert.assertEquals("math/0601001", be.getField("eprint")); + Assert.assertEquals(Optional.of("math/0601001"), be.getFieldOptional("eprint")); Thread.sleep(20000); } @@ -161,7 +163,7 @@ public void testOnline() throws InterruptedException { be = fetcher.importOai2Entry("hep-ph/0408155"); Assert.assertNotNull(be); - Assert.assertEquals("hep-ph/0408155", be.getField("eprint")); + Assert.assertEquals(Optional.of("hep-ph/0408155"), be.getFieldOptional("eprint")); Thread.sleep(20000); } @@ -169,8 +171,8 @@ public void testOnline() throws InterruptedException { be = fetcher.importOai2Entry("0709.3040"); Assert.assertNotNull(be); - Assert.assertEquals("2007", be.getField("year")); - Assert.assertEquals("#sep#", be.getField("month")); + Assert.assertEquals(Optional.of("2007"), be.getFieldOptional("year")); + Assert.assertEquals(Optional.of("#sep#"), be.getFieldOptional("month")); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java index a2a7d4e1e4fd..4688c2af291d 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexImporterTest.java @@ -7,6 +7,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.model.entry.BibEntry; @@ -52,44 +53,51 @@ public void testImportEntries() throws IOException, URISyntaxException { for (BibEntry entry : bibEntries) { if (entry.getCiteKey().equals("aksin")) { - assertEquals("Aks{\\i}n, {\\\"O}zge and T{\\\"u}rkmen, Hayati and Artok, Levent and {\\c{C}}etinkaya, " + - "Bekir and Ni, Chaoying and B{\\\"u}y{\\\"u}kg{\\\"u}ng{\\\"o}r, Orhan and {\\\"O}zkal, Erhan", - entry.getField("author")); - assertEquals("aksin", entry.getField("bibtexkey")); - assertEquals("2006", entry.getField("date")); - assertEquals("Effect of immobilization on catalytic characteristics", entry.getField("indextitle")); - assertEquals("#jomch#", entry.getField("journaltitle")); - assertEquals("13", entry.getField("number")); - assertEquals("3027-3036", entry.getField("pages")); - assertEquals("Effect of immobilization on catalytic characteristics of saturated {Pd-N}-heterocyclic " + - "carbenes in {Mizoroki-Heck} reactions", entry.getField("title")); - assertEquals("691", entry.getField("volume")); + assertEquals( + Optional.of( + "Aks{\\i}n, {\\\"O}zge and T{\\\"u}rkmen, Hayati and Artok, Levent and {\\c{C}}etinkaya, " + + "Bekir and Ni, Chaoying and B{\\\"u}y{\\\"u}kg{\\\"u}ng{\\\"o}r, Orhan and {\\\"O}zkal, Erhan"), + entry.getFieldOptional("author")); + assertEquals(Optional.of("aksin"), entry.getFieldOptional("bibtexkey")); + assertEquals(Optional.of("2006"), entry.getFieldOptional("date")); + assertEquals(Optional.of("Effect of immobilization on catalytic characteristics"), entry.getFieldOptional("indextitle")); + assertEquals(Optional.of("#jomch#"), entry.getFieldOptional("journaltitle")); + assertEquals(Optional.of("13"), entry.getFieldOptional("number")); + assertEquals(Optional.of("3027-3036"), entry.getFieldOptional("pages")); + assertEquals(Optional + .of("Effect of immobilization on catalytic characteristics of saturated {Pd-N}-heterocyclic " + + "carbenes in {Mizoroki-Heck} reactions"), + entry.getFieldOptional("title")); + assertEquals(Optional.of("691"), entry.getFieldOptional("volume")); } else if (entry.getCiteKey().equals("stdmodel")) { - assertEquals("A \\texttt{set} with three members discussing the standard model of particle physics. " + + assertEquals(Optional + .of("A \\texttt{set} with three members discussing the standard model of particle physics. " + "The \\texttt{crossref} field in the \\texttt{@set} entry and the \\texttt{entryset} field in " + - "each set member entry is needed only when using BibTeX as the backend", - entry.getField("annotation")); - assertEquals("stdmodel", entry.getField("bibtexkey")); - assertEquals("glashow,weinberg,salam", entry.getField("entryset")); + "each set member entry is needed only when using BibTeX as the backend"), + entry.getFieldOptional("annotation")); + assertEquals(Optional.of("stdmodel"), entry.getFieldOptional("bibtexkey")); + assertEquals(Optional.of("glashow,weinberg,salam"), entry.getFieldOptional("entryset")); } else if (entry.getCiteKey().equals("set")) { - assertEquals("A \\texttt{set} with three members. The \\texttt{crossref} field in the \\texttt{@set} " + + assertEquals(Optional + .of("A \\texttt{set} with three members. The \\texttt{crossref} field in the \\texttt{@set} " + "entry and the \\texttt{entryset} field in each set member entry is needed only when using " + - "BibTeX as the backend", entry.getField("annotation")); - assertEquals("set", entry.getField("bibtexkey")); - assertEquals("herrmann,aksin,yoon", entry.getField("entryset")); + "BibTeX as the backend"), + entry.getFieldOptional("annotation")); + assertEquals(Optional.of("set"), entry.getFieldOptional("bibtexkey")); + assertEquals(Optional.of("herrmann,aksin,yoon"), entry.getFieldOptional("entryset")); } else if (entry.getCiteKey().equals("Preissel2016")) { - assertEquals("Heidelberg", entry.getField("address")); - assertEquals("Preißel, René", entry.getField("author")); - assertEquals("Preissel2016", entry.getField("bibtexkey")); - assertEquals("3., aktualisierte und erweiterte Auflage", entry.getField("edition")); - assertEquals("978-3-86490-311-3", entry.getField("isbn")); - assertEquals("Versionsverwaltung", entry.getField("keywords")); - assertEquals("XX, 327 Seiten", entry.getField("pages")); - assertEquals("dpunkt.verlag", entry.getField("publisher")); - assertEquals("Git: dezentrale Versionsverwaltung im Team : Grundlagen und Workflows", - entry.getField("title")); - assertEquals("http://d-nb.info/107601965X", entry.getField("url")); - assertEquals("2016", entry.getField("year")); + assertEquals(Optional.of("Heidelberg"), entry.getFieldOptional("address")); + assertEquals(Optional.of("Preißel, René"), entry.getFieldOptional("author")); + assertEquals(Optional.of("Preissel2016"), entry.getFieldOptional("bibtexkey")); + assertEquals(Optional.of("3., aktualisierte und erweiterte Auflage"), entry.getFieldOptional("edition")); + assertEquals(Optional.of("978-3-86490-311-3"), entry.getFieldOptional("isbn")); + assertEquals(Optional.of("Versionsverwaltung"), entry.getFieldOptional("keywords")); + assertEquals(Optional.of("XX, 327 Seiten"), entry.getFieldOptional("pages")); + assertEquals(Optional.of("dpunkt.verlag"), entry.getFieldOptional("publisher")); + assertEquals(Optional.of("Git: dezentrale Versionsverwaltung im Team : Grundlagen und Workflows"), + entry.getFieldOptional("title")); + assertEquals(Optional.of("http://d-nb.info/107601965X"), entry.getFieldOptional("url")); + assertEquals(Optional.of("2016"), entry.getFieldOptional("year")); } } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java index e862aa95f18c..c5d77dc8f8ab 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java @@ -135,7 +135,7 @@ public void parseRecognizesEntry() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -150,7 +150,7 @@ public void parseQuotedEntries() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -178,7 +178,7 @@ public void parseRecognizesEntryWithWhitespaceAtBegining() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -193,7 +193,7 @@ public void parseRecognizesEntryWithWhitespace() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -208,7 +208,7 @@ public void parseRecognizesEntryWithNewlines() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -223,7 +223,7 @@ public void parseRecognizesEntryWithUnknownType() throws IOException { assertEquals("unknown", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -239,7 +239,7 @@ public void parseRecognizesEntryWithVeryLongType() throws IOException { assertEquals("thisisalongstringtotestmaybeitistolongwhoknowsnotme", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -254,7 +254,7 @@ public void parseRecognizesEntryInParenthesis() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } /** @@ -272,9 +272,9 @@ public void parseRecognizesEntryWithBigNumbers() throws IOException { assertEquals("article", e.getType()); assertEquals("canh05", e.getCiteKey()); - assertEquals("1234567890123456789", e.getField("isbn")); - assertEquals("1234567890123456789", e.getField("isbn2")); - assertEquals("1234", e.getField("small")); + assertEquals(Optional.of("1234567890123456789"), e.getFieldOptional("isbn")); + assertEquals(Optional.of("1234567890123456789"), e.getFieldOptional("isbn2")); + assertEquals(Optional.of("1234"), e.getFieldOptional("small")); } @Test @@ -289,7 +289,7 @@ public void parseRecognizesBibtexKeyWithSpecialCharacters() throws IOException { assertEquals("article", e.getType()); assertEquals("te_st:with-special(characters)", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -304,7 +304,7 @@ public void parseRecognizesEntryWhereLastFieldIsFinishedWithComma() throws IOExc assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -389,7 +389,7 @@ public void parseCombinesMultipleAuthorFields() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test and Second Author and Third Author", e.getField("author")); + assertEquals(Optional.of("Ed von Test and Second Author and Third Author"), e.getFieldOptional("author")); } @Test @@ -405,7 +405,7 @@ public void parseCombinesMultipleEditorFields() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test and Second Author and Third Author", e.getField("editor")); + assertEquals(Optional.of("Ed von Test and Second Author and Third Author"), e.getFieldOptional("editor")); } /** @@ -424,7 +424,7 @@ public void parseCombinesMultipleKeywordsFields() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Test, Second Keyword, Third Keyword", e.getField("keywords")); + assertEquals(Optional.of("Test, Second Keyword, Third Keyword"), e.getFieldOptional("keywords")); } @Test @@ -462,13 +462,13 @@ public void parseRecognizesHeaderButIgnoresEncoding() throws IOException { assertEquals("inproceedings", e.getType()); assertEquals(8, e.getFieldNames().size()); assertEquals("CroAnnHow05", e.getCiteKey()); - assertEquals("Crowston, K. and Annabi, H. and Howison, J. and Masango, C.", e.getField("author")); - assertEquals("Effective work practices for floss development: A model and propositions", e.getField("title")); - assertEquals("Hawaii International Conference On System Sciences (HICSS)", e.getField("booktitle")); - assertEquals("2005", e.getField("year")); - assertEquals("oezbek", e.getField("owner")); - assertEquals("2006.05.29", e.getField("timestamp")); - assertEquals("http://james.howison.name/publications.html", e.getField("url")); + assertEquals(Optional.of("Crowston, K. and Annabi, H. and Howison, J. and Masango, C."), e.getFieldOptional("author")); + assertEquals(Optional.of("Effective work practices for floss development: A model and propositions"), e.getFieldOptional("title")); + assertEquals(Optional.of("Hawaii International Conference On System Sciences (HICSS)"), e.getFieldOptional("booktitle")); + assertEquals(Optional.of("2005"), e.getFieldOptional("year")); + assertEquals(Optional.of("oezbek"), e.getFieldOptional("owner")); + assertEquals(Optional.of("2006.05.29"), e.getFieldOptional("timestamp")); + assertEquals(Optional.of("http://james.howison.name/publications.html"), e.getFieldOptional("url")); } @Test @@ -498,13 +498,13 @@ public void parseRecognizesFormatedEntry() throws IOException { assertEquals("inproceedings", e.getType()); assertEquals(8, e.getFieldNames().size()); assertEquals("CroAnnHow05", e.getCiteKey()); - assertEquals("Crowston, K. and Annabi, H. and Howison, J. and Masango, C.", e.getField("author")); - assertEquals("Effective work practices for floss development: A model and propositions", e.getField("title")); - assertEquals("Hawaii International Conference On System Sciences (HICSS)", e.getField("booktitle")); - assertEquals("2005", e.getField("year")); - assertEquals("oezbek", e.getField("owner")); - assertEquals("2006.05.29", e.getField("timestamp")); - assertEquals("http://james.howison.name/publications.html", e.getField("url")); + assertEquals(Optional.of("Crowston, K. and Annabi, H. and Howison, J. and Masango, C."), e.getFieldOptional("author")); + assertEquals(Optional.of("Effective work practices for floss development: A model and propositions"), e.getFieldOptional("title")); + assertEquals(Optional.of("Hawaii International Conference On System Sciences (HICSS)"), e.getFieldOptional("booktitle")); + assertEquals(Optional.of("2005"), e.getFieldOptional("year")); + assertEquals(Optional.of("oezbek"), e.getFieldOptional("owner")); + assertEquals(Optional.of("2006.05.29"), e.getFieldOptional("timestamp")); + assertEquals(Optional.of("http://james.howison.name/publications.html"), e.getFieldOptional("url")); } @Test @@ -519,7 +519,7 @@ public void parseRecognizesFieldValuesInQuotationMarks() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -534,7 +534,7 @@ public void parseRecognizesNumbersWithoutBracketsOrQuotationMarks() throws IOExc assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("2005", e.getField("year")); + assertEquals(Optional.of("2005"), e.getFieldOptional("year")); } @Test @@ -549,7 +549,7 @@ public void parseRecognizesUppercaseFields() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } /** @@ -568,7 +568,7 @@ public void parseRecognizesAbsoluteFile() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("D:\\Documents\\literature\\Tansel-PRL2006.pdf", e.getField("file")); + assertEquals(Optional.of("D:\\Documents\\literature\\Tansel-PRL2006.pdf"), e.getFieldOptional("file")); } /** @@ -586,7 +586,7 @@ public void parseRecognizesDateFieldWithConcatenation() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("1-4~#nov#", e.getField("date")); + assertEquals(Optional.of("1-4~#nov#"), e.getFieldOptional("date")); } @Test @@ -676,7 +676,7 @@ public void parseAddsEscapedOpenBracketToFieldValue() throws IOException { BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); - assertEquals("escaped \\{ bracket", e.getField("review")); + assertEquals(Optional.of("escaped \\{ bracket"), e.getFieldOptional("review")); } @Test @@ -692,7 +692,7 @@ public void parseAddsEscapedClosingBracketToFieldValue() throws IOException { BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); - assertEquals("escaped \\} bracket", e.getField("review")); + assertEquals(Optional.of("escaped \\} bracket"), e.getFieldOptional("review")); } @Test @@ -749,7 +749,7 @@ public void parseAcceptsEntryWithAtSymbolInBrackets() throws IOException { entries.addAll(c); assertEquals(1, entries.size()); - assertEquals("author @ good", entries.get(0).getField("author")); + assertEquals(Optional.of("author @ good"), entries.get(0).getFieldOptional("author")); } @Test @@ -764,7 +764,7 @@ public void parseRecognizesEntryWithAtSymbolInQuotationMarks() throws IOExceptio assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("author @ good", e.getField("author")); + assertEquals(Optional.of("author @ good"), e.getFieldOptional("author")); } @Test @@ -779,7 +779,7 @@ public void parseRecognizesFieldsWithBracketsEnclosedInQuotationMarks() throws I assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Test {Ed {von} Test}", e.getField("author")); + assertEquals(Optional.of("Test {Ed {von} Test}"), e.getFieldOptional("author")); } @Test @@ -795,7 +795,7 @@ public void parseRecognizesFieldsWithEscapedQuotationMarks() throws IOException assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Test {\" Test}", e.getField("author")); + assertEquals(Optional.of("Test {\" Test}"), e.getFieldOptional("author")); } @Test @@ -824,7 +824,7 @@ public void parseIgnoresAndWarnsAboutCorruptedEntryButRecognizeOthers() throws I assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } /** @@ -842,8 +842,8 @@ public void parseRecognizesMonthFieldsWithFollowingComma() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(3, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); - assertEquals("8,", e.getField("month")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); + assertEquals(Optional.of("8,"), e.getFieldOptional("month")); } @Test @@ -976,12 +976,12 @@ public void parseRecognizesStringAndEntry() throws IOException { assertEquals("book", e.getType()); assertEquals("bourdieu-2002-questions-sociologie", e.getCiteKey()); - assertEquals("Paris", e.getField("address")); - assertEquals("#bourdieu#", e.getField("author")); - assertEquals("2707318256", e.getField("isbn")); - assertEquals("Minuit", e.getField("publisher")); - assertEquals("Questions de sociologie", e.getField("title")); - assertEquals("2002", e.getField("year")); + assertEquals(Optional.of("Paris"), e.getFieldOptional("address")); + assertEquals(Optional.of("#bourdieu#"), e.getFieldOptional("author")); + assertEquals(Optional.of("2707318256"), e.getFieldOptional("isbn")); + assertEquals(Optional.of("Minuit"), e.getFieldOptional("publisher")); + assertEquals(Optional.of("Questions de sociologie"), e.getFieldOptional("title")); + assertEquals(Optional.of("2002"), e.getFieldOptional("year")); } @Test @@ -1019,7 +1019,7 @@ public void parseIgnoresCommentsBeforeEntry() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -1034,7 +1034,7 @@ public void parseIgnoresCommentsAfterEntry() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -1056,7 +1056,7 @@ public void parseIgnoresTextBeforeEntry() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -1071,7 +1071,7 @@ public void parseIgnoresTextAfterEntry() throws IOException { assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); assertEquals(2, e.getFieldNames().size()); - assertEquals("Ed von Test", e.getField("author")); + assertEquals(Optional.of("Ed von Test"), e.getFieldOptional("author")); } @Test @@ -1081,7 +1081,7 @@ public void parseConvertsNewlineToSpace() throws IOException { Collection c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); - assertEquals("a b", e.getField("a")); + assertEquals(Optional.of("a b"), e.getFieldOptional("a")); } @Test @@ -1092,9 +1092,9 @@ public void parseConvertsMultipleNewlinesToSpace() throws IOException { Collection c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); - assertEquals("a b", e.getField("a")); - assertEquals("a b", e.getField("b")); - assertEquals("a b", e.getField("c")); + assertEquals(Optional.of("a b"), e.getFieldOptional("a")); + assertEquals(Optional.of("a b"), e.getFieldOptional("b")); + assertEquals(Optional.of("a b"), e.getFieldOptional("c")); } @Test @@ -1104,7 +1104,7 @@ public void parseConvertsTabToSpace() throws IOException { Collection c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); - assertEquals("a b", e.getField("a")); + assertEquals(Optional.of("a b"), e.getFieldOptional("a")); } @Test @@ -1115,9 +1115,9 @@ public void parseConvertsMultipleTabsToSpace() throws IOException { Collection c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); - assertEquals("a b", e.getField("a")); - assertEquals("a b", e.getField("b")); - assertEquals("a b", e.getField("c")); + assertEquals(Optional.of("a b"), e.getFieldOptional("a")); + assertEquals(Optional.of("a b"), e.getFieldOptional("b")); + assertEquals(Optional.of("a b"), e.getFieldOptional("c")); } /** @@ -1132,7 +1132,7 @@ public void parsePreservesMultipleSpacesInFileField() throws IOException { Collection c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); - assertEquals("ups sala", e.getField("file")); + assertEquals(Optional.of("ups sala"), e.getFieldOptional("file")); } /** @@ -1148,7 +1148,7 @@ public void parseRemovesTabsInFileField() throws IOException { Collection c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); - assertEquals("ups sala", e.getField("file")); + assertEquals(Optional.of("ups sala"), e.getFieldOptional("file")); } /** @@ -1164,7 +1164,7 @@ public void parseRemovesNewlineInFileField() throws IOException { Collection c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); - assertEquals("ups sala", e.getField("file")); + assertEquals(Optional.of("ups sala"), e.getFieldOptional("file")); } /** @@ -1182,7 +1182,7 @@ public void parseHandlesAccentsCorrectly() throws IOException { BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); - assertEquals("H\'{e}lne Fiaux", e.getField("author")); + assertEquals(Optional.of("H\'{e}lne Fiaux"), e.getFieldOptional("author")); } /** @@ -1203,7 +1203,7 @@ public void parsePreambleAndEntryWithoutNewLine() throws IOException { BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals("test", e.getCiteKey()); - assertEquals("H\'{e}lne Fiaux", e.getField("author")); + assertEquals(Optional.of("H\'{e}lne Fiaux"), e.getFieldOptional("author")); } /** @@ -1511,7 +1511,7 @@ public void parsePrecedingComment() throws IOException { assertEquals(5, entry.getFieldNames().size()); Set fields = entry.getFieldNames(); assertTrue(fields.contains("author")); - assertEquals("Foo Bar", entry.getField("author")); + assertEquals(Optional.of("Foo Bar"), entry.getFieldOptional("author")); assertEquals(bibtexEntry, entry.getParsedSerialization()); } @@ -1537,7 +1537,7 @@ public void parseCommentAndEntryInOneLine() throws IOException { assertEquals(5, entry.getFieldNames().size()); Set fields = entry.getFieldNames(); assertTrue(fields.contains("author")); - assertEquals("Foo Bar", entry.getField("author")); + assertEquals(Optional.of("Foo Bar"), entry.getFieldOptional("author")); assertEquals(bibtexEntry, entry.getParsedSerialization()); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java index 6c04829241fc..2677bcdbee24 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/EndnoteImporterTest.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.model.entry.BibEntry; @@ -90,40 +91,40 @@ public void testImportEntries0() throws IOException, URISyntaxException { BibEntry be0 = bibEntries.get(0); assertEquals("misc", be0.getType()); - assertEquals("testA0 and testA1", be0.getField("author")); - assertEquals("testE0 and testE1", be0.getField("editor")); - assertEquals("testT", be0.getField("title")); + assertEquals(Optional.of("testA0 and testA1"), be0.getFieldOptional("author")); + assertEquals(Optional.of("testE0 and testE1"), be0.getFieldOptional("editor")); + assertEquals(Optional.of("testT"), be0.getFieldOptional("title")); BibEntry be1 = bibEntries.get(1); assertEquals("misc", be1.getType()); - assertEquals("testC", be1.getField("address")); - assertEquals("testB2", be1.getField("booktitle")); - assertEquals("test8", be1.getField("date")); - assertEquals("test7", be1.getField("edition")); - assertEquals("testJ", be1.getField("journal")); - assertEquals("testD", be1.getField("year")); + assertEquals(Optional.of("testC"), be1.getFieldOptional("address")); + assertEquals(Optional.of("testB2"), be1.getFieldOptional("booktitle")); + assertEquals(Optional.of("test8"), be1.getFieldOptional("date")); + assertEquals(Optional.of("test7"), be1.getFieldOptional("edition")); + assertEquals(Optional.of("testJ"), be1.getFieldOptional("journal")); + assertEquals(Optional.of("testD"), be1.getFieldOptional("year")); BibEntry be2 = bibEntries.get(2); assertEquals("article", be2.getType()); - assertEquals("testB0", be2.getField("journal")); + assertEquals(Optional.of("testB0"), be2.getFieldOptional("journal")); BibEntry be3 = bibEntries.get(3); assertEquals("book", be3.getType()); - assertEquals("testI0", be3.getField("publisher")); - assertEquals("testB1", be3.getField("series")); + assertEquals(Optional.of("testI0"), be3.getFieldOptional("publisher")); + assertEquals(Optional.of("testB1"), be3.getFieldOptional("series")); BibEntry be4 = bibEntries.get(4); assertEquals("mastersthesis", be4.getType()); - assertEquals("testX", be4.getField("abstract")); - assertEquals("testF", be4.getField("bibtexkey")); - assertEquals("testR", be4.getField("doi")); - assertEquals("testK", be4.getField("keywords")); - assertEquals("testO1", be4.getField("note")); - assertEquals("testN", be4.getField("number")); - assertEquals("testP", be4.getField("pages")); - assertEquals("testI1", be4.getField("school")); - assertEquals("testU", be4.getField("url")); - assertEquals("testV", be4.getField("volume")); + assertEquals(Optional.of("testX"), be4.getFieldOptional("abstract")); + assertEquals(Optional.of("testF"), be4.getFieldOptional("bibtexkey")); + assertEquals(Optional.of("testR"), be4.getFieldOptional("doi")); + assertEquals(Optional.of("testK"), be4.getFieldOptional("keywords")); + assertEquals(Optional.of("testO1"), be4.getFieldOptional("note")); + assertEquals(Optional.of("testN"), be4.getFieldOptional("number")); + assertEquals(Optional.of("testP"), be4.getFieldOptional("pages")); + assertEquals(Optional.of("testI1"), be4.getFieldOptional("school")); + assertEquals(Optional.of("testU"), be4.getFieldOptional("url")); + assertEquals(Optional.of("testV"), be4.getFieldOptional("volume")); } @Test @@ -135,9 +136,9 @@ public void testImportEntries1() throws IOException { BibEntry be = bibEntries.get(0); assertEquals("misc", be.getType()); - assertEquals("testA", be.getField("author")); - assertEquals("testE0, testE1", be.getField("editor")); - assertEquals("testO", be.getField("pages")); + assertEquals(Optional.of("testA"), be.getFieldOptional("author")); + assertEquals(Optional.of("testE0, testE1"), be.getFieldOptional("editor")); + assertEquals(Optional.of("testO"), be.getFieldOptional("pages")); } @Test @@ -149,14 +150,14 @@ public void testImportEntriesBookExample() throws IOException, URISyntaxExceptio BibEntry be = bibEntries.get(0); assertEquals("book", be.getType()); - assertEquals("Heidelberg", be.getField("address")); - assertEquals("Preißel, René and Stachmann, Bjørn", be.getField("author")); - assertEquals("3., aktualisierte und erweiterte Auflage", be.getField("edition")); - assertEquals("Versionsverwaltung", be.getField("keywords")); - assertEquals("XX, 327", be.getField("pages")); - assertEquals("dpunkt.verlag", be.getField("publisher")); - assertEquals("Git : dezentrale Versionsverwaltung im Team : Grundlagen und Workflows", be.getField("title")); - assertEquals("http://d-nb.info/107601965X", be.getField("url")); - assertEquals("2016", be.getField("year")); + assertEquals(Optional.of("Heidelberg"), be.getFieldOptional("address")); + assertEquals(Optional.of("Preißel, René and Stachmann, Bjørn"), be.getFieldOptional("author")); + assertEquals(Optional.of("3., aktualisierte und erweiterte Auflage"), be.getFieldOptional("edition")); + assertEquals(Optional.of("Versionsverwaltung"), be.getFieldOptional("keywords")); + assertEquals(Optional.of("XX, 327"), be.getFieldOptional("pages")); + assertEquals(Optional.of("dpunkt.verlag"), be.getFieldOptional("publisher")); + assertEquals(Optional.of("Git : dezentrale Versionsverwaltung im Team : Grundlagen und Workflows"), be.getFieldOptional("title")); + assertEquals(Optional.of("http://d-nb.info/107601965X"), be.getFieldOptional("url")); + assertEquals(Optional.of("2016"), be.getFieldOptional("year")); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java index 21ed2bea6ee2..c118a2542036 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/IsiImporterTest.java @@ -8,6 +8,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.model.entry.BibEntry; @@ -133,17 +134,18 @@ public void testImportEntries1() throws IOException, URISyntaxException { List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(1, entries.size()); BibEntry entry = entries.get(0); - Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); + Assert.assertEquals(Optional.of("Optical properties of MgO doped LiNbO$_3$ single crystals"), entry.getFieldOptional("title")); Assert.assertEquals( - "James Brown and James Marc Brown and Brown, J. M. and Brown, J. and Brown, J. M. and Brown, J.", - entry.getField("author")); + Optional.of( + "James Brown and James Marc Brown and Brown, J. M. and Brown, J. and Brown, J. M. and Brown, J."), + entry.getFieldOptional("author")); Assert.assertEquals("article", entry.getType()); - Assert.assertEquals("Optical Materials", entry.getField("journal")); - Assert.assertEquals("2006", entry.getField("year")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("5", entry.getField("number")); - Assert.assertEquals("467--72", entry.getField("pages")); + Assert.assertEquals(Optional.of("Optical Materials"), entry.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("2006"), entry.getFieldOptional("year")); + Assert.assertEquals(Optional.of("28"), entry.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("5"), entry.getFieldOptional("number")); + Assert.assertEquals(Optional.of("467--72"), entry.getFieldOptional("pages")); } @Test @@ -152,14 +154,14 @@ public void testImportEntries2() throws IOException, URISyntaxException { List entries = importer.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); Assert.assertEquals(3, entries.size()); BibEntry entry = entries.get(0); - Assert.assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry.getField("title")); + Assert.assertEquals(Optional.of("Optical properties of MgO doped LiNbO$_3$ single crystals"), entry.getFieldOptional("title")); Assert.assertEquals("misc", entry.getType()); - Assert.assertEquals("Optical Materials", entry.getField("journal")); - Assert.assertEquals("2006", entry.getField("year")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("5", entry.getField("number")); - Assert.assertEquals("467-72", entry.getField("pages")); + Assert.assertEquals(Optional.of("Optical Materials"), entry.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("2006"), entry.getFieldOptional("year")); + Assert.assertEquals(Optional.of("28"), entry.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("5"), entry.getFieldOptional("number")); + Assert.assertEquals(Optional.of("467-72"), entry.getFieldOptional("pages")); } @Test @@ -171,29 +173,31 @@ public void testImportEntriesINSPEC() throws IOException, URISyntaxException { BibEntry a = entries.get(0); BibEntry b = entries.get(1); - if (a.getField("title") - .equals("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals")) { + if (a.getFieldOptional("title").equals( + Optional.of("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals"))) { BibEntry tmp = a; a = b; b = tmp; } Assert.assertEquals( - "Second harmonic generation of continuous wave ultraviolet light and production of beta -BaB$_2$O$_4$ optical waveguides", - a.getField("title")); + Optional.of( + "Second harmonic generation of continuous wave ultraviolet light and production of beta -BaB$_2$O$_4$ optical waveguides"), + a.getFieldOptional("title")); Assert.assertEquals("article", a.getType()); - Assert.assertEquals("Degl'Innocenti, R. and Guarino, A. and Poberaj, G. and Gunter, P.", a.getField("author")); - Assert.assertEquals("Applied Physics Letters", a.getField("journal")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals("#jul#", a.getField("month")); - Assert.assertEquals("89", a.getField("volume")); - Assert.assertEquals("4", a.getField("number")); - Assert.assertEquals("Lorem ipsum abstract", a.getField("abstract")); - Assert.assertEquals("Aip", a.getField("publisher")); - - Assert.assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals", - b.getField("title")); + Assert.assertEquals(Optional.of("Degl'Innocenti, R. and Guarino, A. and Poberaj, G. and Gunter, P."), a.getFieldOptional("author")); + Assert.assertEquals(Optional.of("Applied Physics Letters"), a.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("2006"), a.getFieldOptional("year")); + Assert.assertEquals(Optional.of("#jul#"), a.getFieldOptional("month")); + Assert.assertEquals(Optional.of("89"), a.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("4"), a.getFieldOptional("number")); + Assert.assertEquals(Optional.of("Lorem ipsum abstract"), a.getFieldOptional("abstract")); + Assert.assertEquals(Optional.of("Aip"), a.getFieldOptional("publisher")); + + Assert.assertEquals( + Optional.of("Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals"), + b.getFieldOptional("title")); Assert.assertEquals("article", b.getType()); } @@ -206,12 +210,12 @@ public void testImportEntriesWOS() throws IOException, URISyntaxException { BibEntry a = entries.get(0); BibEntry b = entries.get(1); - Assert.assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn2P2S6 crystals", - a.getField("title")); - Assert.assertEquals("Optical waveguides in Sn2P2S6 by low fluence MeV He+ ion implantation", - b.getField("title")); + Assert.assertEquals(Optional.of("Optical and photoelectric spectroscopy of photorefractive Sn2P2S6 crystals"), + a.getFieldOptional("title")); + Assert.assertEquals(Optional.of("Optical waveguides in Sn2P2S6 by low fluence MeV He+ ion implantation"), + b.getFieldOptional("title")); - Assert.assertEquals("Journal of Physics-condensed Matter", a.getField("journal")); + Assert.assertEquals(Optional.of("Journal of Physics-condensed Matter"), a.getFieldOptional("journal")); } @Test @@ -262,18 +266,18 @@ public void testImportIEEEExport() throws IOException, URISyntaxException { Assert.assertEquals(1, entries.size()); BibEntry a = entries.get(0); Assert.assertEquals("article", a.getType()); - Assert.assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal")); - Assert.assertEquals("Improving Urban Road Extraction in High-Resolution " - + "Images Exploiting Directional Filtering, Perceptual " + "Grouping, and Simple Topological Concepts", - a.getField("title")); - Assert.assertEquals("4", a.getField("volume")); - Assert.assertEquals("3", a.getField("number")); - Assert.assertEquals("1545-598X", a.getField("SN")); - Assert.assertEquals("387--391", a.getField("pages")); - Assert.assertEquals("Gamba, P. and Dell'Acqua, F. and Lisini, G.", a.getField("author")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals("Perceptual grouping, street extraction, urban remote sensing", a.getField("keywords")); - Assert.assertEquals("Lorem ipsum abstract", a.getField("abstract")); + Assert.assertEquals(Optional.of("Geoscience and Remote Sensing Letters, IEEE"), a.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("Improving Urban Road Extraction in High-Resolution " + + "Images Exploiting Directional Filtering, Perceptual " + "Grouping, and Simple Topological Concepts"), + a.getFieldOptional("title")); + Assert.assertEquals(Optional.of("4"), a.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("3"), a.getFieldOptional("number")); + Assert.assertEquals(Optional.of("1545-598X"), a.getFieldOptional("SN")); + Assert.assertEquals(Optional.of("387--391"), a.getFieldOptional("pages")); + Assert.assertEquals(Optional.of("Gamba, P. and Dell'Acqua, F. and Lisini, G."), a.getFieldOptional("author")); + Assert.assertEquals(Optional.of("2006"), a.getFieldOptional("year")); + Assert.assertEquals(Optional.of("Perceptual grouping, street extraction, urban remote sensing"), a.getFieldOptional("keywords")); + Assert.assertEquals(Optional.of("Lorem ipsum abstract"), a.getFieldOptional("abstract")); } @Test @@ -285,18 +289,19 @@ public void testIEEEImport() throws IOException, URISyntaxException { BibEntry a = entries.get(0); Assert.assertEquals("article", a.getType()); - Assert.assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal")); + Assert.assertEquals(Optional.of("Geoscience and Remote Sensing Letters, IEEE"), a.getFieldOptional("journal")); Assert.assertEquals( - "Improving Urban Road Extraction in High-Resolution Images Exploiting Directional Filtering, Perceptual Grouping, and Simple Topological Concepts", - a.getField("title")); - Assert.assertEquals("4", a.getField("volume")); - Assert.assertEquals("3", a.getField("number")); - Assert.assertEquals("1545-598X", a.getField("SN")); - Assert.assertEquals("387--391", a.getField("pages")); - Assert.assertEquals("Gamba, P. and Dell'Acqua, F. and Lisini, G.", a.getField("author")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals("Perceptual grouping, street extraction, urban remote sensing", a.getField("keywords")); - Assert.assertEquals("Lorem ipsum abstract", a.getField("abstract")); + Optional.of( + "Improving Urban Road Extraction in High-Resolution Images Exploiting Directional Filtering, Perceptual Grouping, and Simple Topological Concepts"), + a.getFieldOptional("title")); + Assert.assertEquals(Optional.of("4"), a.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("3"), a.getFieldOptional("number")); + Assert.assertEquals(Optional.of("1545-598X"), a.getFieldOptional("SN")); + Assert.assertEquals(Optional.of("387--391"), a.getFieldOptional("pages")); + Assert.assertEquals(Optional.of("Gamba, P. and Dell'Acqua, F. and Lisini, G."), a.getFieldOptional("author")); + Assert.assertEquals(Optional.of("2006"), a.getFieldOptional("year")); + Assert.assertEquals(Optional.of("Perceptual grouping, street extraction, urban remote sensing"), a.getFieldOptional("keywords")); + Assert.assertEquals(Optional.of("Lorem ipsum abstract"), a.getFieldOptional("abstract")); } @Test @@ -309,29 +314,32 @@ public void testImportEntriesMedline() throws IOException, URISyntaxException { BibEntry a = entries.get(0); BibEntry b = entries.get(1); - Assert.assertEquals("Effects of modafinil on cognitive performance and alertness during sleep deprivation.", - a.getField("title")); - - Assert.assertEquals("Wesensten, Nancy J.", a.getField("author")); - Assert.assertEquals("Curr Pharm Des", a.getField("journal")); - Assert.assertEquals("2006", a.getField("year")); - Assert.assertEquals(null, a.getField("month")); - Assert.assertEquals("12", a.getField("volume")); - Assert.assertEquals("20", a.getField("number")); - Assert.assertEquals("2457--71", a.getField("pages")); + Assert.assertEquals( + Optional.of("Effects of modafinil on cognitive performance and alertness during sleep deprivation."), + a.getFieldOptional("title")); + + Assert.assertEquals(Optional.of("Wesensten, Nancy J."), a.getFieldOptional("author")); + Assert.assertEquals(Optional.of("Curr Pharm Des"), a.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("2006"), a.getFieldOptional("year")); + Assert.assertEquals(Optional.empty(), a.getFieldOptional("month")); + Assert.assertEquals(Optional.of("12"), a.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("20"), a.getFieldOptional("number")); + Assert.assertEquals(Optional.of("2457--71"), a.getFieldOptional("pages")); Assert.assertEquals("article", a.getType()); Assert.assertEquals( - "Estrogen therapy selectively enhances prefrontal cognitive processes: a randomized, double-blind, placebo-controlled study with functional magnetic resonance imaging in perimenopausal and recently postmenopausal women.", - b.getField("title")); + Optional.of( + "Estrogen therapy selectively enhances prefrontal cognitive processes: a randomized, double-blind, placebo-controlled study with functional magnetic resonance imaging in perimenopausal and recently postmenopausal women."), + b.getFieldOptional("title")); Assert.assertEquals( - "Joffe, Hadine and Hall, Janet E. and Gruber, Staci and Sarmiento, Ingrid A. and Cohen, Lee S. and Yurgelun-Todd, Deborah and Martin, Kathryn A.", - b.getField("author")); - Assert.assertEquals("2006", b.getField("year")); - Assert.assertEquals("#may#", b.getField("month")); - Assert.assertEquals("13", b.getField("volume")); - Assert.assertEquals("3", b.getField("number")); - Assert.assertEquals("411--22", b.getField("pages")); + Optional.of( + "Joffe, Hadine and Hall, Janet E. and Gruber, Staci and Sarmiento, Ingrid A. and Cohen, Lee S. and Yurgelun-Todd, Deborah and Martin, Kathryn A."), + b.getFieldOptional("author")); + Assert.assertEquals(Optional.of("2006"), b.getFieldOptional("year")); + Assert.assertEquals(Optional.of("#may#"), b.getFieldOptional("month")); + Assert.assertEquals(Optional.of("13"), b.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("3"), b.getFieldOptional("number")); + Assert.assertEquals(Optional.of("411--22"), b.getFieldOptional("pages")); Assert.assertEquals("article", b.getType()); } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/JSONEntryParserTest.java b/src/test/java/net/sf/jabref/importer/fileformat/JSONEntryParserTest.java index 65297284bf33..172f1b27f0d9 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/JSONEntryParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/JSONEntryParserTest.java @@ -16,6 +16,8 @@ package net.sf.jabref.importer.fileformat; +import java.util.Optional; + import net.sf.jabref.model.entry.BibEntry; import org.json.JSONObject; @@ -40,13 +42,14 @@ public void testBibJSONConverter() { BibEntry be = jc.parseBibJSONtoBibtex(jo); Assert.assertEquals("article", be.getType()); - Assert.assertEquals("VLSI Design", be.getField("journal")); - Assert.assertEquals("10.1155/2014/217495", be.getField("doi")); - Assert.assertEquals("Syed Asad Alam and Oscar Gustafsson", be.getField("author")); + Assert.assertEquals(Optional.of("VLSI Design"), be.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("10.1155/2014/217495"), be.getFieldOptional("doi")); + Assert.assertEquals(Optional.of("Syed Asad Alam and Oscar Gustafsson"), be.getFieldOptional("author")); Assert.assertEquals( - "Design of Finite Word Length Linear-Phase FIR Filters in the Logarithmic Number System Domain", - be.getField("title")); - Assert.assertEquals("2014", be.getField("year")); + Optional.of( + "Design of Finite Word Length Linear-Phase FIR Filters in the Logarithmic Number System Domain"), + be.getFieldOptional("title")); + Assert.assertEquals(Optional.of("2014"), be.getFieldOptional("year")); } @Test @@ -63,13 +66,13 @@ public void testSpringerJSONToBibtex() { JSONObject jo = new JSONObject(jsonString); BibEntry be = JSONEntryParser.parseSpringerJSONtoBibtex(jo); - Assert.assertEquals("1992", be.getField("year")); - Assert.assertEquals("5", be.getField("number")); - Assert.assertEquals("#sep#", be.getField("month")); - Assert.assertEquals("10.1007/BF01201962", be.getField("doi")); - Assert.assertEquals("8", be.getField("volume")); - Assert.assertEquals("Springer", be.getField("publisher")); - Assert.assertEquals("1992-09-01", be.getField("date")); + Assert.assertEquals(Optional.of("1992"), be.getFieldOptional("year")); + Assert.assertEquals(Optional.of("5"), be.getFieldOptional("number")); + Assert.assertEquals(Optional.of("#sep#"), be.getFieldOptional("month")); + Assert.assertEquals(Optional.of("10.1007/BF01201962"), be.getFieldOptional("doi")); + Assert.assertEquals(Optional.of("8"), be.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("Springer"), be.getFieldOptional("publisher")); + Assert.assertEquals(Optional.of("1992-09-01"), be.getFieldOptional("date")); } } diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java index f1c69d61492f..8c7aed816e9f 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlinePlainImporterTest.java @@ -12,6 +12,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.logic.bibtex.BibEntryAssert; @@ -91,31 +92,33 @@ public void testImportMultipleEntriesInSingleFile() throws IOException, URISynta BibEntry testEntry = entries.get(0); assertEquals("article", testEntry.getType()); - Assert.assertNull(testEntry.getField("month")); - assertEquals("Long, Vicky and Marland, Hilary", testEntry.getField("author")); + assertEquals(Optional.empty(), testEntry.getFieldOptional("month")); + assertEquals(Optional.of("Long, Vicky and Marland, Hilary"), testEntry.getFieldOptional("author")); assertEquals( - "From danger and motherhood to health and beauty: health advice for the factory girl in early twentieth-century Britain.", - testEntry.getField("title")); + Optional.of( + "From danger and motherhood to health and beauty: health advice for the factory girl in early twentieth-century Britain."), + testEntry.getFieldOptional("title")); testEntry = entries.get(1); assertEquals("conference", testEntry.getType()); - assertEquals("06", testEntry.getField("month")); - Assert.assertNull(testEntry.getField("author")); - Assert.assertNull(testEntry.getField("title")); + assertEquals(Optional.of("06"), testEntry.getFieldOptional("month")); + assertEquals(Optional.empty(), testEntry.getFieldOptional("author")); + assertEquals(Optional.empty(), testEntry.getFieldOptional("title")); testEntry = entries.get(2); assertEquals("book", testEntry.getType()); assertEquals( - "This is a Testtitle: This title should be appended: This title should also be appended. Another append to the Title? LastTitle", - testEntry.getField("title")); + Optional.of( + "This is a Testtitle: This title should be appended: This title should also be appended. Another append to the Title? LastTitle"), + testEntry.getFieldOptional("title")); testEntry = entries.get(3); assertEquals("techreport", testEntry.getType()); - Assert.assertNotNull(testEntry.getField("doi")); + Assert.assertTrue(testEntry.getFieldOptional("doi").isPresent()); testEntry = entries.get(4); assertEquals("inproceedings", testEntry.getType()); - assertEquals("Inproceedings book title", testEntry.getField("booktitle")); + assertEquals(Optional.of("Inproceedings book title"), testEntry.getFieldOptional("booktitle")); BibEntry expectedEntry5 = new BibEntry(); expectedEntry5.setType("proceedings"); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java index c7e003083949..760afdadea94 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/OvidImporterTest.java @@ -9,6 +9,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.logic.bibtex.BibEntryAssert; @@ -88,49 +89,49 @@ public void testImportEntries1() throws IOException, URISyntaxException { BibEntry entry = entries.get(0); Assert.assertEquals("misc", entry.getType()); - Assert.assertEquals("Mustermann and Musterfrau", entry.getField("author")); - Assert.assertEquals("Short abstract", entry.getField("abstract")); - Assert.assertEquals("Musterbuch", entry.getField("title")); - Assert.assertEquals("Einleitung", entry.getField("chaptertitle")); + Assert.assertEquals(Optional.of("Mustermann and Musterfrau"), entry.getFieldOptional("author")); + Assert.assertEquals(Optional.of("Short abstract"), entry.getFieldOptional("abstract")); + Assert.assertEquals(Optional.of("Musterbuch"), entry.getFieldOptional("title")); + Assert.assertEquals(Optional.of("Einleitung"), entry.getFieldOptional("chaptertitle")); entry = entries.get(1); Assert.assertEquals("inproceedings", entry.getType()); - Assert.assertEquals("Max", entry.getField("editor")); - Assert.assertEquals("Max the Editor", entry.getField("title")); - Assert.assertEquals("Very Long Title", entry.getField("journal")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("2", entry.getField("issue")); - Assert.assertEquals("2015", entry.getField("year")); - Assert.assertEquals("103--106", entry.getField("pages")); + Assert.assertEquals(Optional.of("Max"), entry.getFieldOptional("editor")); + Assert.assertEquals(Optional.of("Max the Editor"), entry.getFieldOptional("title")); + Assert.assertEquals(Optional.of("Very Long Title"), entry.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("28"), entry.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("2"), entry.getFieldOptional("issue")); + Assert.assertEquals(Optional.of("2015"), entry.getFieldOptional("year")); + Assert.assertEquals(Optional.of("103--106"), entry.getFieldOptional("pages")); entry = entries.get(2); Assert.assertEquals("incollection", entry.getType()); - Assert.assertEquals("Max", entry.getField("author")); - Assert.assertEquals("Test", entry.getField("title")); - Assert.assertEquals("Very Long Title", entry.getField("journal")); - Assert.assertEquals("28", entry.getField("volume")); - Assert.assertEquals("2", entry.getField("issue")); - Assert.assertEquals("April", entry.getField("month")); - Assert.assertEquals("2015", entry.getField("year")); - Assert.assertEquals("103--106", entry.getField("pages")); + Assert.assertEquals(Optional.of("Max"), entry.getFieldOptional("author")); + Assert.assertEquals(Optional.of("Test"), entry.getFieldOptional("title")); + Assert.assertEquals(Optional.of("Very Long Title"), entry.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("28"), entry.getFieldOptional("volume")); + Assert.assertEquals(Optional.of("2"), entry.getFieldOptional("issue")); + Assert.assertEquals(Optional.of("April"), entry.getFieldOptional("month")); + Assert.assertEquals(Optional.of("2015"), entry.getFieldOptional("year")); + Assert.assertEquals(Optional.of("103--106"), entry.getFieldOptional("pages")); entry = entries.get(3); Assert.assertEquals("book", entry.getType()); - Assert.assertEquals("Max", entry.getField("author")); - Assert.assertEquals("2015", entry.getField("year")); - Assert.assertEquals("Editor", entry.getField("editor")); - Assert.assertEquals("Very Long Title", entry.getField("booktitle")); - Assert.assertEquals("103--106", entry.getField("pages")); - Assert.assertEquals("Address", entry.getField("address")); - Assert.assertEquals("Publisher", entry.getField("publisher")); + Assert.assertEquals(Optional.of("Max"), entry.getFieldOptional("author")); + Assert.assertEquals(Optional.of("2015"), entry.getFieldOptional("year")); + Assert.assertEquals(Optional.of("Editor"), entry.getFieldOptional("editor")); + Assert.assertEquals(Optional.of("Very Long Title"), entry.getFieldOptional("booktitle")); + Assert.assertEquals(Optional.of("103--106"), entry.getFieldOptional("pages")); + Assert.assertEquals(Optional.of("Address"), entry.getFieldOptional("address")); + Assert.assertEquals(Optional.of("Publisher"), entry.getFieldOptional("publisher")); entry = entries.get(4); Assert.assertEquals("article", entry.getType()); - Assert.assertEquals("2014", entry.getField("year")); - Assert.assertEquals("58", entry.getField("pages")); - Assert.assertEquals("Test", entry.getField("address")); - Assert.assertNull(entry.getField("title")); - Assert.assertEquals("TestPublisher", entry.getField("publisher")); + Assert.assertEquals(Optional.of("2014"), entry.getFieldOptional("year")); + Assert.assertEquals(Optional.of("58"), entry.getFieldOptional("pages")); + Assert.assertEquals(Optional.of("Test"), entry.getFieldOptional("address")); + Assert.assertEquals(Optional.empty(), entry.getFieldOptional("title")); + Assert.assertEquals(Optional.of("TestPublisher"), entry.getFieldOptional("publisher")); } @Test diff --git a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java index e2063e0c37d2..ab6147538e20 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/PdfXmpImporterTest.java @@ -7,6 +7,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; import net.sf.jabref.importer.ParserResult; @@ -62,10 +63,10 @@ public void testImportEntries() throws IOException, URISyntaxException { assertEquals(1, bibEntries.size()); BibEntry be0 = bibEntries.get(0); - assertEquals("how to annotate a pdf", be0.getField("abstract")); - assertEquals("Chris", be0.getField("author")); - assertEquals("pdf, annotation", be0.getField("keywords")); - assertEquals("The best Pdf ever", be0.getField("title")); + assertEquals(Optional.of("how to annotate a pdf"), be0.getFieldOptional("abstract")); + assertEquals(Optional.of("Chris"), be0.getFieldOptional("author")); + assertEquals(Optional.of("pdf, annotation"), be0.getFieldOptional("keywords")); + assertEquals(Optional.of("The best Pdf ever"), be0.getFieldOptional("title")); } @Test diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index 8a12be0e5bdc..4fef99dfbbef 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; +import java.util.Optional; import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; @@ -104,8 +105,8 @@ public void upgradeExternalLinksMoveFromPdfToFile() { entry.setField("pdf", "aPdfFile"); worker.cleanup(preset, entry); - Assert.assertEquals(null, entry.getField("pdf")); - Assert.assertEquals("aPdfFile:aPdfFile:PDF", entry.getField("file")); + Assert.assertEquals(Optional.empty(), entry.getFieldOptional("pdf")); + Assert.assertEquals(Optional.of("aPdfFile:aPdfFile:PDF"), entry.getFieldOptional("file")); } @Test @@ -115,8 +116,8 @@ public void upgradeExternalLinksMoveFromPsToFile() { entry.setField("ps", "aPsFile"); worker.cleanup(preset, entry); - Assert.assertEquals(null, entry.getField("pdf")); - Assert.assertEquals("aPsFile:aPsFile:PostScript", entry.getField("file")); + Assert.assertEquals(Optional.empty(), entry.getFieldOptional("pdf")); + Assert.assertEquals(Optional.of("aPsFile:aPsFile:PostScript"), entry.getFieldOptional("file")); } @Test @@ -126,7 +127,7 @@ public void cleanupDoiRemovesLeadingHttp() { entry.setField("doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); worker.cleanup(preset, entry); - Assert.assertEquals("10.1016/0001-8708(80)90035-3", entry.getField("doi")); + Assert.assertEquals(Optional.of("10.1016/0001-8708(80)90035-3"), entry.getFieldOptional("doi")); } @Test @@ -149,8 +150,8 @@ public void cleanupDoiFindsDoiInURLFieldAndMoveItToDOIField() { entry.setField("url", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); worker.cleanup(preset, entry); - Assert.assertEquals("10.1016/0001-8708(80)90035-3", entry.getField("doi")); - Assert.assertNull(entry.getField("url")); + Assert.assertEquals(Optional.of("10.1016/0001-8708(80)90035-3"), entry.getFieldOptional("doi")); + Assert.assertEquals(Optional.empty(), entry.getFieldOptional("url")); } @Test @@ -174,7 +175,7 @@ public void cleanupMonthChangesNumberToBibtex() { entry.setField("month", "01"); worker.cleanup(preset, entry); - Assert.assertEquals("#jan#", entry.getField("month")); + Assert.assertEquals(Optional.of("#jan#"), entry.getFieldOptional("month")); } @Test @@ -185,7 +186,7 @@ public void cleanupPageNumbersConvertsSingleDashToDouble() { entry.setField("pages", "1-2"); worker.cleanup(preset, entry); - Assert.assertEquals("1--2", entry.getField("pages")); + Assert.assertEquals(Optional.of("1--2"), entry.getFieldOptional("pages")); } @Test @@ -196,7 +197,7 @@ public void cleanupDatesConvertsToCorrectFormat() { entry.setField("date", "01/1999"); worker.cleanup(preset, entry); - Assert.assertEquals("1999-01", entry.getField("date")); + Assert.assertEquals(Optional.of("1999-01"), entry.getFieldOptional("date")); } @Test @@ -206,7 +207,7 @@ public void cleanupFixFileLinksMovesSingleDescriptionToLink() { entry.setField("file", "link::"); worker.cleanup(preset, entry); - Assert.assertEquals(":link:", entry.getField("file")); + Assert.assertEquals(Optional.of(":link:"), entry.getFieldOptional("file")); } @Test @@ -222,7 +223,8 @@ public void cleanupMoveFilesMovesFileFromSubfolder() throws IOException { worker.cleanup(preset, entry); ParsedFileField newFileField = new ParsedFileField("", tempFile.getName(), ""); - Assert.assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + Assert.assertEquals(Optional.of(FileField.getStringRepresentation(newFileField)), + entry.getFieldOptional("file")); } @Test @@ -236,7 +238,8 @@ public void cleanupRelativePathsConvertAbsoluteToRelativePath() throws IOExcepti worker.cleanup(preset, entry); ParsedFileField newFileField = new ParsedFileField("", tempFile.getName(), ""); - Assert.assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + Assert.assertEquals(Optional.of(FileField.getStringRepresentation(newFileField)), + entry.getFieldOptional("file")); } @Test @@ -251,7 +254,8 @@ public void cleanupRenamePdfRenamesRelativeFile() throws IOException { worker.cleanup(preset, entry); ParsedFileField newFileField = new ParsedFileField("", "Toot.tmp", ""); - Assert.assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + Assert.assertEquals(Optional.of(FileField.getStringRepresentation(newFileField)), + entry.getFieldOptional("file")); } @Test @@ -262,7 +266,7 @@ public void cleanupHtmlToLatexConvertsEpsilonToLatex() { entry.setField("title", "Ε"); worker.cleanup(preset, entry); - Assert.assertEquals("{{$\\Epsilon$}}", entry.getField("title")); + Assert.assertEquals(Optional.of("{{$\\Epsilon$}}"), entry.getFieldOptional("title")); } @Test @@ -273,7 +277,7 @@ public void cleanupUnitsConvertsOneAmpereToLatex() { entry.setField("title", "1 A"); worker.cleanup(preset, entry); - Assert.assertEquals("1~{A}", entry.getField("title")); + Assert.assertEquals(Optional.of("1~{A}"), entry.getFieldOptional("title")); } @Test @@ -284,7 +288,7 @@ public void cleanupCasesAddsBracketAroundAluminiumGalliumArsenid() { entry.setField("title", "AlGaAs"); worker.cleanup(preset, entry); - Assert.assertEquals("{AlGaAs}", entry.getField("title")); + Assert.assertEquals(Optional.of("{AlGaAs}"), entry.getFieldOptional("title")); } @Test @@ -295,7 +299,7 @@ public void cleanupLatexMergesTwoLatexMathEnvironments() { entry.setField("title", "$\\alpha$$\\beta$"); worker.cleanup(preset, entry); - Assert.assertEquals("$\\alpha\\beta$", entry.getField("title")); + Assert.assertEquals(Optional.of("$\\alpha\\beta$"), entry.getFieldOptional("title")); } @Test @@ -305,8 +309,8 @@ public void convertToBiblatexMovesJournalToJournalTitle() { entry.setField("journal", "test"); worker.cleanup(preset, entry); - Assert.assertEquals(null, entry.getField("journal")); - Assert.assertEquals("test", entry.getField("journaltitle")); + Assert.assertEquals(Optional.empty(), entry.getFieldOptional("journal")); + Assert.assertEquals(Optional.of("test"), entry.getFieldOptional("journaltitle")); } @Test @@ -317,6 +321,6 @@ public void cleanupWithDisabledFieldFormatterChangesNothing() { entry.setField("month", "01"); worker.cleanup(preset, entry); - Assert.assertEquals("01", entry.getField("month")); + Assert.assertEquals(Optional.of("01"), entry.getFieldOptional("month")); } } diff --git a/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java index 7e0e6100b1a7..4962fc3d1731 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/MoveFilesCleanupTest.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; +import java.util.Optional; import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; @@ -60,7 +61,8 @@ public void movesFileFromSubfolder() throws IOException { File fileAfter = new File(pdfFolder, "test.pdf"); assertTrue(fileAfter.exists()); - assertEquals(FileField.getStringRepresentation(new ParsedFileField("", fileAfter.getName(), "")), entry.getField("file")); + assertEquals(Optional.of(FileField.getStringRepresentation(new ParsedFileField("", fileAfter.getName(), ""))), + entry.getFieldOptional("file")); } @Test @@ -80,7 +82,9 @@ public void movesFileFromSubfolderMultiple() throws IOException { File fileAfter = new File(pdfFolder, "test.pdf"); assertTrue(fileAfter.exists()); - assertEquals(FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), - new ParsedFileField("", fileAfter.getName(), ""), new ParsedFileField("","",""))), entry.getField("file")); + assertEquals( + Optional.of(FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("", "", ""), + new ParsedFileField("", fileAfter.getName(), ""), new ParsedFileField("", "", "")))), + entry.getFieldOptional("file")); } } \ No newline at end of file diff --git a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java index 5690d16efeb6..3af235826000 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; +import java.util.Optional; import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Defaults; @@ -57,7 +58,7 @@ public void cleanupRenamePdfRenamesFileEvenIfOnlyDifferenceIsCase() throws IOExc cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot.tmp", ""); - assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + assertEquals(Optional.of(FileField.getStringRepresentation(newFileField)), entry.getFieldOptional("file")); } @Test @@ -72,8 +73,10 @@ public void cleanupRenamePdfRenamesWithMultipleFiles() throws IOException { RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); cleanup.cleanup(entry); - assertEquals(FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), - new ParsedFileField("", "Toot - test title.tmp", ""), new ParsedFileField("","",""))), entry.getField("file")); + assertEquals( + Optional.of(FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("", "", ""), + new ParsedFileField("", "Toot - test title.tmp", ""), new ParsedFileField("", "", "")))), + entry.getFieldOptional("file")); } @Test @@ -88,7 +91,7 @@ public void cleanupRenamePdfRenamesFileStartingWithBibtexKey() throws IOExceptio cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot - test title.tmp", ""); - assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + assertEquals(Optional.of(FileField.getStringRepresentation(newFileField)), entry.getFieldOptional("file")); } @Test @@ -103,6 +106,6 @@ public void cleanupRenamePdfRenamesFileInSameFolder() throws IOException { cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot - test title.pdf", "PDF"); - assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + assertEquals(Optional.of(FileField.getStringRepresentation(newFileField)), entry.getFieldOptional("file")); } } diff --git a/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java b/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java index 2662eaddf5d9..6ba3e6b5a162 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/FieldFormatterCleanupsTest.java @@ -58,7 +58,7 @@ public void checkSimpleUseCase() { actions.applySaveActions(entry); - assertEquals("Educational session 1", entry.getField("title")); + assertEquals(Optional.of("Educational session 1"), entry.getFieldOptional("title")); } @Test @@ -70,7 +70,7 @@ public void invalidSaveActionSting() { actions.applySaveActions(entry); - assertEquals("Educational session 1", entry.getField("title")); + assertEquals(Optional.of("Educational session 1"), entry.getFieldOptional("title")); } @Test @@ -83,7 +83,7 @@ public void checkLowerCaseSaveAction() { actions.applySaveActions(entry); - assertEquals("educational session 1", entry.getField("title")); + assertEquals(Optional.of("educational session 1"), entry.getFieldOptional("title")); } @Test @@ -96,7 +96,7 @@ public void checkTwoSaveActionsForOneField() { actions.applySaveActions(entry); - assertEquals("educational session 1", entry.getField("title")); + assertEquals(Optional.of("educational session 1"), entry.getFieldOptional("title")); } @Test @@ -111,7 +111,7 @@ public void checkThreeSaveActionsForOneField() { actions.applySaveActions(entry); - assertEquals("educational session 1", entry.getField("title")); + assertEquals(Optional.of("educational session 1"), entry.getFieldOptional("title")); } @Test @@ -126,8 +126,8 @@ public void checkMultipleSaveActions() { actions.applySaveActions(entry); - assertEquals("educational session 1", entry.getField("title")); - assertEquals("1--7", entry.getField("pages")); + assertEquals(Optional.of("educational session 1"), entry.getFieldOptional("title")); + assertEquals(Optional.of("1--7"), entry.getFieldOptional("pages")); } @Test @@ -144,8 +144,8 @@ public void checkMultipleSaveActionsWithMultipleFormatters() { actions.applySaveActions(entry); - assertEquals("educational session 1", entry.getField("title")); - assertEquals("1--7", entry.getField("pages")); + assertEquals(Optional.of("educational session 1"), entry.getFieldOptional("title")); + assertEquals(Optional.of("1--7"), entry.getFieldOptional("pages")); } @Test diff --git a/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java b/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java index 86a1f1bd26f7..abe04bc1842f 100644 --- a/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java +++ b/src/test/java/net/sf/jabref/logic/util/UpdateFieldTest.java @@ -29,14 +29,14 @@ public void setUp() throws Exception { public void testUpdateFieldWorksEmptyField() { assertFalse(entry.hasField("year")); UpdateField.updateField(entry, "year", "2016"); - assertEquals("2016", entry.getField("year")); + assertEquals(Optional.of("2016"), entry.getFieldOptional("year")); } @Test public void testUpdateFieldWorksNonEmptyField() { entry.setField("year", "2015"); UpdateField.updateField(entry, "year", "2016"); - assertEquals("2016", entry.getField("year")); + assertEquals(Optional.of("2016"), entry.getFieldOptional("year")); } @Test @@ -159,7 +159,7 @@ public void testUpdateNonDisplayableFieldUpdates() { assertFalse(entry.hasField("year")); UpdateField.updateNonDisplayableField(entry, "year", "2016"); assertTrue(entry.hasField("year")); - assertEquals("2016", entry.getField("year")); + assertEquals(Optional.of("2016"), entry.getFieldOptional("year")); } @Test diff --git a/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java b/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java index b016bcfc203c..92c234d85bfa 100644 --- a/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java +++ b/src/test/java/net/sf/jabref/logic/xmp/XMPSchemaBibtexTest.java @@ -39,7 +39,7 @@ public void assertEqualsBibtexEntry(BibEntry e, BibEntry x) { Assert.assertEquals(e.getFieldNames().size(), x.getFieldNames().size()); for (String name : e.getFieldNames()) { - Assert.assertEquals(e.getField(name), x.getField(name)); + Assert.assertEquals(e.getFieldOptional(name), x.getFieldOptional(name)); } } From ad09d78872d4cabecb283c0440e919f57ffa0ddf Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 20 Jul 2016 08:16:08 +0200 Subject: [PATCH 251/268] Added filter to not show selected integrity checks (#1588) * Added filter to not show selected integrity checks * Removed unused variable --- CHANGELOG.md | 1 + .../gui/actions/IntegrityCheckAction.java | 64 ++++++++++++++++--- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d087aef5ee..a03a55556256 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings - [#1249](https://github.com/JabRef/jabref/issues/1249) Date layout formatter added - Added ISBN integrity checker +- Added filter to not show selected integrity checks ### Fixed - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly diff --git a/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java b/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java index 77084fba6eb6..b772f1c94830 100644 --- a/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/IntegrityCheckAction.java @@ -1,14 +1,23 @@ package net.sf.jabref.gui.actions; import java.awt.event.ActionEvent; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JCheckBoxMenuItem; import javax.swing.JDialog; import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; +import javax.swing.RowFilter; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; import net.sf.jabref.Globals; import net.sf.jabref.gui.JabRefFrame; @@ -17,6 +26,9 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.preferences.JabRefPreferences; +import com.jgoodies.forms.builder.FormBuilder; +import com.jgoodies.forms.layout.FormLayout; + public class IntegrityCheckAction extends MnemonicAwareAction { private static final String ELLIPSES = "..."; @@ -38,6 +50,7 @@ public void actionPerformed(ActionEvent e) { if (messages.isEmpty()) { JOptionPane.showMessageDialog(frame.getCurrentBasePanel(), Localization.lang("No problems found.")); } else { + Map showMessage = new HashMap<>(); // prepare data model Object[][] model = new Object[messages.size()][3]; int i = 0; @@ -45,6 +58,7 @@ public void actionPerformed(ActionEvent e) { model[i][0] = message.getEntry().getCiteKey(); model[i][1] = message.getFieldName(); model[i][2] = message.getMessage(); + showMessage.put(message.getMessage(), true); i++; } @@ -53,30 +67,62 @@ public void actionPerformed(ActionEvent e) { new Object[] {Localization.lang("BibTeX key"), Localization.lang("Field"), Localization.lang("Message")}); - table.setAutoCreateRowSorter(true); + RowFilter filter = new RowFilter() { + + @Override + public boolean include(Entry entry) { + return showMessage.get(entry.getStringValue(2)); + } + }; + + TableRowSorter sorter = new TableRowSorter<>(table.getModel()); + sorter.setRowFilter(filter); + table.setRowSorter(sorter); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setDefaultEditor(Object.class, null); ListSelectionModel selectionModel = table.getSelectionModel(); + selectionModel.addListSelectionListener(event -> { if (!event.getValueIsAdjusting()) { - String citeKey = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][0]; - String fieldName = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][1]; - frame.getCurrentBasePanel().editEntryByKeyAndFocusField(citeKey, fieldName); + try { + String citeKey = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][0]; + String fieldName = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][1]; + frame.getCurrentBasePanel().editEntryByKeyAndFocusField(citeKey, fieldName); + } catch (ArrayIndexOutOfBoundsException exception) { + // Ignore -- most likely caused by filtering out the earlier selected row + } } }); table.setRowHeight(Globals.prefs.getInt(JabRefPreferences.MENU_FONT_SIZE) + 2); - table.getColumnModel().getColumn(0).setPreferredWidth(80); - table.getColumnModel().getColumn(1).setPreferredWidth(30); - table.getColumnModel().getColumn(2).setPreferredWidth(250); + table.getColumnModel().getColumn(0).setPreferredWidth(100); + table.getColumnModel().getColumn(1).setPreferredWidth(60); + table.getColumnModel().getColumn(2).setPreferredWidth(400); table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); JScrollPane scrollPane = new JScrollPane(table); String title = Localization.lang("%0 problem(s) found", String.valueOf(messages.size())); JDialog dialog = new JDialog(frame, title, false); - dialog.add(scrollPane); - dialog.setSize(600, 500); + + JPopupMenu menu = new JPopupMenu(); + for (String messageString : showMessage.keySet()) { + JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(messageString, true); + menuItem.addActionListener(event -> { + showMessage.put(messageString, menuItem.isSelected()); + ((AbstractTableModel) table.getModel()).fireTableDataChanged(); + }); + menu.add(menuItem); + } + JButton menuButton = new JButton(Localization.lang("Filter")); + menuButton.addActionListener(entry -> menu.show(menuButton, 0, menuButton.getHeight())); + FormBuilder builder = FormBuilder.create() + .layout(new FormLayout("fill:pref:grow", "fill:pref:grow, 2dlu, pref")); + + builder.add(scrollPane).xy(1, 1); + builder.add(menuButton).xy(1, 3, "c, b"); + dialog.add(builder.getPanel()); + dialog.setSize(600, 600); // show view dialog.setVisible(true); From 90044ac423016f8b5931ea6a4067ff314ed3047a Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 20 Jul 2016 09:41:58 +0200 Subject: [PATCH 252/268] Some Globals.prefs injection in logic and model (#1593) * Some Globals.prefs injection in logic and model * Some more conversions and some fixes * More injections * Even more injections * Yes, even more injections * Indeed, even more injections * Probably the last injections for now * Removed unrequired dependency and fixed issue * Dropped support for selecting sub/super to equations * Added preference classes for LatexFieldFormatter and FieldContentParser * Removed some left over code * Added JournalAbbreviationPreferences * Encapsulated LatexFieldFormatterPreferences in SavePreferences * Changed getShortDescription to accept boolean argument * Removed Globals.prefs from tests and removed unused imports * Unused import * Unused import --- CHANGELOG.md | 1 + .../net/sf/jabref/benchmarks/Benchmarks.java | 2 +- src/main/java/net/sf/jabref/JabRefMain.java | 4 +- src/main/java/net/sf/jabref/MetaData.java | 4 +- .../net/sf/jabref/cli/ArgumentProcessor.java | 4 +- .../net/sf/jabref/external/AutoSetLinks.java | 2 +- .../jabref/external/DownloadExternalFile.java | 3 +- .../jabref/external/DroppedFileHandler.java | 5 +- .../sf/jabref/external/MoveFileAction.java | 2 +- .../java/net/sf/jabref/gui/BasePanel.java | 8 +-- .../sf/jabref/gui/ImportInspectionDialog.java | 4 +- .../java/net/sf/jabref/gui/JabRefFrame.java | 2 +- .../java/net/sf/jabref/gui/PreviewPanel.java | 3 +- .../java/net/sf/jabref/gui/StringDialog.java | 4 +- .../jabref/gui/TransferableBibtexEntry.java | 5 +- .../sf/jabref/gui/actions/CleanupAction.java | 2 +- .../gui/actions/ManageKeywordsAction.java | 4 +- .../jabref/gui/entryeditor/EntryEditor.java | 13 ++-- .../gui/entryeditor/FieldExtraComponents.java | 4 +- .../sf/jabref/gui/exporter/ExportAction.java | 2 +- .../exporter/ExportCustomizationDialog.java | 56 +++++++-------- .../sf/jabref/gui/groups/AutoGroupDialog.java | 5 +- .../net/sf/jabref/gui/groups/GroupDialog.java | 10 +-- .../gui/groups/GroupTreeNodeViewModel.java | 6 +- .../jabref/gui/journals/AbbreviateAction.java | 5 +- .../gui/journals/ManageJournalsPanel.java | 7 +- .../gui/journals/UnabbreviateAction.java | 4 +- .../gui/labelpattern/LabelPatternPanel.java | 2 +- .../SearchFixDuplicateLabels.java | 4 +- .../jabref/gui/mergeentries/MergeEntries.java | 4 +- .../gui/openoffice/OpenOfficePanel.java | 3 +- .../gui/plaintextimport/TextInputDialog.java | 7 +- .../sf/jabref/gui/preftabs/AdvancedTab.java | 10 +-- .../gui/preftabs/PreferencesDialog.java | 2 +- .../sf/jabref/gui/preftabs/TablePrefsTab.java | 3 +- .../jabref/gui/worker/SendAsEMailAction.java | 5 +- .../jabref/importer/AppendDatabaseAction.java | 2 +- .../jabref/importer/EntryFromPDFCreator.java | 3 +- .../importer/fetcher/ACMPortalFetcher.java | 4 +- .../importer/fetcher/CiteSeerXFetcher.java | 3 +- .../jabref/importer/fetcher/DBLPFetcher.java | 9 ++- .../fetcher/GoogleScholarFetcher.java | 13 ++-- .../importer/fetcher/IEEEXploreFetcher.java | 41 ++++------- .../fetcher/ScienceDirectFetcher.java | 3 +- .../importer/fileformat/BibtexParser.java | 7 +- .../importer/fileformat/FreeCiteImporter.java | 4 +- .../importer/fileformat/JSONEntryParser.java | 4 +- .../importer/fileformat/PdfXmpImporter.java | 5 +- .../importer/fileformat/RepecNepImporter.java | 5 +- .../AutoCompletePreferences.java | 5 ++ .../autocompleter/AutoCompleterFactory.java | 1 + .../autocompleter/JournalAutoCompleter.java | 10 ++- .../logic/bibtex/FieldContentParser.java | 9 +-- .../bibtex/FieldContentParserPreferences.java | 30 ++++++++ .../logic/bibtex/LatexFieldFormatter.java | 42 +++++------ .../LatexFieldFormatterPreferences.java | 64 +++++++++++++++++ .../bibtex/comparator/FieldComparator.java | 26 +++---- .../jabref/logic/cleanup/CleanupWorker.java | 9 ++- .../logic/cleanup/RenamePdfCleanup.java | 7 +- .../logic/exporter/BibDatabaseWriter.java | 26 ++++--- .../logic/exporter/BibtexDatabaseWriter.java | 15 ++-- .../logic/exporter/CustomExportList.java | 25 ++++--- .../jabref/logic/exporter/ExportFormat.java | 8 +-- .../jabref/logic/exporter/ExportFormats.java | 4 +- .../logic/exporter/SavePreferences.java | 35 +++++---- .../bibtexfields/HtmlToLatexFormatter.java | 14 +--- .../sf/jabref/logic/groups/AbstractGroup.java | 9 +-- .../jabref/logic/groups/AllEntriesGroup.java | 2 +- .../sf/jabref/logic/groups/ExplicitGroup.java | 14 ++-- .../sf/jabref/logic/groups/GroupTreeNode.java | 6 +- .../sf/jabref/logic/groups/GroupsParser.java | 6 +- .../sf/jabref/logic/groups/KeywordGroup.java | 21 +++--- .../sf/jabref/logic/groups/SearchGroup.java | 10 ++- .../journals/JournalAbbreviationLoader.java | 19 +++-- .../JournalAbbreviationPreferences.java | 46 ++++++++++++ .../labelpattern/DatabaseLabelPattern.java | 11 ++- .../logic/labelpattern/LabelPatternUtil.java | 11 ++- .../net/sf/jabref/logic/layout/Layout.java | 7 +- .../sf/jabref/logic/layout/LayoutEntry.java | 29 +++++--- .../sf/jabref/logic/layout/LayoutHelper.java | 7 +- .../jabref/logic/layout/format/FileLink.java | 12 +++- .../layout/format/JournalAbbreviator.java | 9 ++- .../logic/layout/format/NameFormatter.java | 8 +-- .../logic/layout/format/WrapFileLinks.java | 13 +++- .../net/sf/jabref/logic/net/URLDownload.java | 6 -- .../jabref/logic/openoffice/OOBibStyle.java | 15 ++-- .../jabref/logic/openoffice/StyleLoader.java | 14 ++-- .../net/sf/jabref/logic/util/io/FileUtil.java | 11 +-- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 35 ++++----- .../net/sf/jabref/model/entry/BibEntry.java | 14 ++-- .../model/entry/InternalBibtexFields.java | 22 +++--- .../net/sf/jabref/pdfimport/PdfImporter.java | 9 +-- .../jabref/preferences/JabRefPreferences.java | 2 - .../specialfields/SpecialFieldsUtils.java | 4 +- .../jabref/sql/importer/DatabaseImporter.java | 5 +- src/main/resources/l10n/JabRef_da.properties | 1 - src/main/resources/l10n/JabRef_de.properties | 1 - src/main/resources/l10n/JabRef_en.properties | 1 - src/main/resources/l10n/JabRef_es.properties | 1 - src/main/resources/l10n/JabRef_fa.properties | 1 - src/main/resources/l10n/JabRef_fr.properties | 1 - src/main/resources/l10n/JabRef_in.properties | 1 - src/main/resources/l10n/JabRef_it.properties | 1 - src/main/resources/l10n/JabRef_ja.properties | 1 - src/main/resources/l10n/JabRef_nl.properties | 1 - src/main/resources/l10n/JabRef_no.properties | 1 - .../resources/l10n/JabRef_pt_BR.properties | 1 - src/main/resources/l10n/JabRef_ru.properties | 1 - src/main/resources/l10n/JabRef_sv.properties | 1 - src/main/resources/l10n/JabRef_tr.properties | 1 - src/main/resources/l10n/JabRef_vi.properties | 1 - src/main/resources/l10n/JabRef_zh.properties | 1 - .../ConvertLegacyExplicitGroupsTest.java | 4 +- .../importer/fileformat/BibtexParserTest.java | 8 ++- .../AutoCompleterFactoryTest.java | 3 + .../logic/bibtex/BibEntryWriterTest.java | 3 +- .../logic/bibtex/FieldContentParserTest.java | 2 +- .../bibtex/LatexFieldFormatterTests.java | 2 +- .../logic/cleanup/CleanupWorkerTest.java | 2 +- .../logic/cleanup/RenamePdfCleanupTest.java | 12 ++-- .../exporter/BibtexDatabaseWriterTest.java | 11 +-- .../logic/exporter/ExportFormatTest.java | 2 +- .../logic/exporter/HtmlExportFormatTest.java | 2 +- .../logic/groups/ExplicitGroupTest.java | 4 +- .../logic/groups/GroupTreeNodeTest.java | 71 +++++++++++-------- .../jabref/logic/groups/KeywordGroupTest.java | 26 ++++--- .../jabref/logic/groups/SearchGroupTest.java | 2 +- .../logic/journals/AbbreviationsTest.java | 16 +++-- .../jabref/logic/layout/LayoutEntryTest.java | 2 +- .../sf/jabref/logic/layout/LayoutTest.java | 2 +- .../logic/layout/format/FileLinkTest.java | 14 ++-- .../sf/jabref/logic/net/URLDownloadTest.java | 3 +- .../logic/openoffice/OOBibStyleTest.java | 56 +++++++-------- .../logic/openoffice/StyleLoaderTest.java | 32 ++++----- .../jabref/logic/search/SearchQueryTest.java | 2 +- .../sf/jabref/logic/util/io/FileUtilTest.java | 8 ++- .../logic/util/io/UtilFindFileTest.java | 3 +- .../net/sf/jabref/logic/xmp/XMPUtilTest.java | 68 +++++++++--------- .../sf/jabref/model/entry/BibEntryTests.java | 55 ++++++++------ .../jabref/sql/DatabaseImportExportTests.java | 3 +- 140 files changed, 874 insertions(+), 582 deletions(-) create mode 100644 src/main/java/net/sf/jabref/logic/bibtex/FieldContentParserPreferences.java create mode 100644 src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterPreferences.java create mode 100644 src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationPreferences.java diff --git a/CHANGELOG.md b/CHANGELOG.md index a03a55556256..1e81b4856701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed [#1592](https://github.com/JabRef/jabref/issues/1592): LibreOffice: wrong numbers in citation labels ### Removed +- It is not longer possible to choose to convert HTML sub- and superscripts to equations diff --git a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java index e1a03ce04233..59bf3e6758d4 100644 --- a/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/net/sf/jabref/benchmarks/Benchmarks.java @@ -122,7 +122,7 @@ public String htmlToLatexConversion() { @Benchmark public boolean keywordGroupContains() throws ParseException { KeywordGroup group = new KeywordGroup("testGroup", "keyword", "testkeyword", false, false, - GroupHierarchyType.INDEPENDENT); + GroupHierarchyType.INDEPENDENT, Globals.prefs); return group.containsAll(database.getEntries()); } diff --git a/src/main/java/net/sf/jabref/JabRefMain.java b/src/main/java/net/sf/jabref/JabRefMain.java index 48329e11b43d..4470fc7aed16 100644 --- a/src/main/java/net/sf/jabref/JabRefMain.java +++ b/src/main/java/net/sf/jabref/JabRefMain.java @@ -61,12 +61,12 @@ private static void start(String[] args) { Globals.prefs.setLanguageDependentDefaultValues(); // Update which fields should be treated as numeric, based on preferences: - InternalBibtexFields.setNumericFieldsFromPrefs(); + InternalBibtexFields.setNumericFields(Globals.prefs.getStringList(JabRefPreferences.NUMERIC_FIELDS)); /* Build list of Import and Export formats */ Globals.IMPORT_FORMAT_READER.resetImportFormats(); CustomEntryTypesManager.loadCustomEntryTypes(preferences); - ExportFormats.initAllExports(); + ExportFormats.initAllExports(Globals.prefs.customExports.getCustomExportFormats(Globals.prefs)); // Read list(s) of journal names and abbreviations Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(); diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index de4646a45111..1a6369da8e5c 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -178,7 +178,7 @@ public void putData(String key, List orderedData) { */ private void putGroups(List orderedData) throws ParseException { try { - groupsRoot = GroupTreeNode.parse(orderedData); + groupsRoot = GroupTreeNode.parse(orderedData, Globals.prefs); } catch (ParseException e) { throw new ParseException(Localization.lang( "Group tree could not be parsed. If you save the BibTeX database, all groups will be lost."), e); @@ -238,7 +238,7 @@ public AbstractLabelPattern getLabelPattern() { return labelPattern; } - labelPattern = new DatabaseLabelPattern(); + labelPattern = new DatabaseLabelPattern(Globals.prefs); // read the data from the metadata and store it into the labelPattern for (String key : this) { diff --git a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java index cfc25c77d115..4f61e9976a13 100644 --- a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java @@ -390,7 +390,7 @@ private void importPreferences() { try { Globals.prefs.importPreferences(cli.getPreferencesImport()); CustomEntryTypesManager.loadCustomEntryTypes(Globals.prefs); - ExportFormats.initAllExports(); + ExportFormats.initAllExports(Globals.prefs.customExports.getCustomExportFormats(Globals.prefs)); } catch (JabRefException ex) { LOGGER.error("Cannot import preferences", ex); } @@ -435,7 +435,7 @@ private void regenerateBibtexKeys(List loaded) { LOGGER.info(Localization.lang("Regenerating BibTeX keys according to metadata")); for (BibEntry entry : database.getEntries()) { // try to make a new label - LabelPatternUtil.makeLabel(metaData, database, entry); + LabelPatternUtil.makeLabel(metaData, database, entry, Globals.prefs); } } else { LOGGER.info(Localization.lang("No meta data present in bibfile. Cannot regenerate BibTeX keys")); diff --git a/src/main/java/net/sf/jabref/external/AutoSetLinks.java b/src/main/java/net/sf/jabref/external/AutoSetLinks.java index 7346c9e48619..41968bced887 100644 --- a/src/main/java/net/sf/jabref/external/AutoSetLinks.java +++ b/src/main/java/net/sf/jabref/external/AutoSetLinks.java @@ -104,7 +104,7 @@ public void run() { String regExp = Globals.prefs.get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY); result = RegExpFileSearch.findFilesForSet(entries, extensions, dirs, regExp); } else { - result = FileUtil.findAssociatedFiles(entries, extensions, dirs); + result = FileUtil.findAssociatedFiles(entries, extensions, dirs, Globals.prefs); } boolean foundAny = false; diff --git a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java index 12cc76d7ee47..450fc458d372 100644 --- a/src/main/java/net/sf/jabref/external/DownloadExternalFile.java +++ b/src/main/java/net/sf/jabref/external/DownloadExternalFile.java @@ -270,7 +270,8 @@ private void downloadFinished() { // FIXME: will break download if no bibtexkey is present! private String getSuggestedFileName(String suffix) { String plannedName = FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), - frame.getCurrentBasePanel().getSelectedEntries().get(0), Globals.journalAbbreviationLoader); + frame.getCurrentBasePanel().getSelectedEntries().get(0), Globals.journalAbbreviationLoader, + Globals.prefs); if (!suffix.isEmpty()) { plannedName += "." + suffix; diff --git a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java index 83c166f7caf4..351eba391c59 100644 --- a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java +++ b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java @@ -233,7 +233,7 @@ private boolean tryXmpImport(String fileName, ExternalFileType fileType, NamedCo List xmpEntriesInFile; try { - xmpEntriesInFile = XMPUtil.readXMP(fileName); + xmpEntriesInFile = XMPUtil.readXMP(fileName, Globals.prefs); } catch (IOException e) { LOGGER.warn("Problem reading XMP", e); return false; @@ -350,7 +350,8 @@ private boolean showLinkMoveCopyRenameDialog(String linkFileName, ExternalFileTy renameCheckBox.setText(Localization.lang("Rename file to").concat(": ")); // Determine which name to suggest: - String targetName = FileUtil.createFileNameFromPattern(database, entry, Globals.journalAbbreviationLoader); + String targetName = FileUtil.createFileNameFromPattern(database, entry, Globals.journalAbbreviationLoader, + Globals.prefs); renameToTextBox.setText(targetName.concat(".").concat(fileType.getExtension())); diff --git a/src/main/java/net/sf/jabref/external/MoveFileAction.java b/src/main/java/net/sf/jabref/external/MoveFileAction.java index d39339c4b05d..b4bc662daa20 100644 --- a/src/main/java/net/sf/jabref/external/MoveFileAction.java +++ b/src/main/java/net/sf/jabref/external/MoveFileAction.java @@ -112,7 +112,7 @@ public void actionPerformed(ActionEvent event) { // Determine which name to suggest: String suggName = FileUtil .createFileNameFromPattern(eEditor.getDatabase(), eEditor.getEntry(), - Globals.journalAbbreviationLoader) + Globals.journalAbbreviationLoader, Globals.prefs) .concat(entry.type.isPresent() ? "." + entry.type.get().getExtension() : ""); CheckBoxMessage cbm = new CheckBoxMessage(Localization.lang("Move file to file directory?"), Localization.lang("Rename to '%0'", suggName), diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index bf221b400852..8e0f54bfafff 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -575,7 +575,7 @@ public void run() { // Finally, set the new keys: for (BibEntry entry : entries) { bes = entry; - LabelPatternUtil.makeLabel(bibDatabaseContext.getMetaData(), database, bes); + LabelPatternUtil.makeLabel(bibDatabaseContext.getMetaData(), database, bes, Globals.prefs); ce.addEdit(new UndoableKeyChange(database, bes, (String) oldvals.get(bes), bes.getCiteKey())); } @@ -990,7 +990,7 @@ private void copyKeyAndTitle() { "\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); Layout layout; try { - layout = new LayoutHelper(sr, Globals.journalAbbreviationLoader).getLayoutFromText(); + layout = new LayoutHelper(sr, Globals.prefs, Globals.journalAbbreviationLoader).getLayoutFromText(); } catch (IOException e) { LOGGER.info("Could not get layout", e); return; @@ -1987,7 +1987,7 @@ public void autoGenerateKeysBeforeSaving() { for (BibEntry bes : database.getEntries()) { String oldKey = bes.getCiteKey(); if ((oldKey == null) || oldKey.isEmpty()) { - LabelPatternUtil.makeLabel(bibDatabaseContext.getMetaData(), database, bes); + LabelPatternUtil.makeLabel(bibDatabaseContext.getMetaData(), database, bes, Globals.prefs); ce.addEdit(new UndoableKeyChange(database, bes, null, bes.getCiteKey())); any = true; } @@ -2425,7 +2425,7 @@ public Optional searchAndOpen() { String regExp = Globals.prefs.get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY); result = RegExpFileSearch.findFilesForSet(entries, extensions, dirs, regExp); } else { - result = FileUtil.findAssociatedFiles(entries, extensions, dirs); + result = FileUtil.findAssociatedFiles(entries, extensions, dirs, Globals.prefs); } if (result.containsKey(entry)) { final List res = result.get(entry); diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 563b05d814e4..61323de91345 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -461,7 +461,7 @@ private void generateKeySelectedEntry() { database.insertEntry(entry); // Generate a unique key: - LabelPatternUtil.makeLabel(localMetaData, database, entry); + LabelPatternUtil.makeLabel(localMetaData, database, entry, Globals.prefs); // Remove the entry from the database again, since we only added it in // order to // make sure the key was unique: @@ -502,7 +502,7 @@ private void generateKeys() { entry.setId(IdGenerator.next()); database.insertEntry(entry); - LabelPatternUtil.makeLabel(localMetaData, database, entry); + LabelPatternUtil.makeLabel(localMetaData, database, entry, Globals.prefs); // Add the generated key to our list: keys.add(entry.getCiteKey()); } diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index c3c7a04ed296..43eb7976d417 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -776,7 +776,7 @@ private void tearDownJabRef(List filenames) { } fileHistory.storeHistory(); - prefs.customExports.store(); + prefs.customExports.store(Globals.prefs); prefs.customImports.store(); CustomEntryTypesManager.saveCustomEntryTypes(prefs); diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index e0bcca474347..f516c01d47c6 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -261,7 +261,8 @@ public void updateLayout(String layoutFormat) { private void updateLayout() { StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); try { - layout = Optional.of(new LayoutHelper(sr, Globals.journalAbbreviationLoader).getLayoutFromText()); + layout = Optional + .of(new LayoutHelper(sr, Globals.prefs, Globals.journalAbbreviationLoader).getLayoutFromText()); } catch (IOException e) { layout = Optional.empty(); LOGGER.debug("no layout could be set", e); diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index a0c6f6074630..50a5d4ec512b 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -55,6 +55,7 @@ import net.sf.jabref.gui.undo.UndoableStringChange; import net.sf.jabref.gui.util.PositionWindow; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.bibtex.comparator.BibtexStringComparator; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; @@ -266,7 +267,8 @@ public void setValueAt(Object value, int row, int col) { if (!value.equals(subject.getContent())) { try { - new LatexFieldFormatter().format((String) value, "__dummy"); + new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)) + .format((String) value, "__dummy"); } catch (IllegalArgumentException ex) { return; } diff --git a/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java b/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java index e156548f28ae..9245af85f726 100644 --- a/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java +++ b/src/main/java/net/sf/jabref/gui/TransferableBibtexEntry.java @@ -24,8 +24,10 @@ import javax.swing.JOptionPane; +import net.sf.jabref.Globals; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; @@ -63,7 +65,8 @@ public Object getTransferData(DataFlavor flavor) } else if (flavor.equals(DataFlavor.stringFlavor)) { try { StringWriter sw = new StringWriter(); - BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new LatexFieldFormatter(), false); + BibEntryWriter bibtexEntryWriter = new BibEntryWriter( + new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)), false); for (BibEntry entry : data) { bibtexEntryWriter.write(entry, sw, BibDatabaseMode.BIBTEX); } diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java index a41b5b68d161..dca00432fa49 100644 --- a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java @@ -161,7 +161,7 @@ private int showDialog(CleanupPresetPanel presetPanel) { private void doCleanup(CleanupPreset preset, BibEntry entry, NamedCompound ce) { // Create and run cleaner BibDatabaseContext bibDatabaseContext = panel.getBibDatabaseContext(); - CleanupWorker cleaner = new CleanupWorker(bibDatabaseContext, Globals.journalAbbreviationLoader); + CleanupWorker cleaner = new CleanupWorker(bibDatabaseContext, Globals.journalAbbreviationLoader, Globals.prefs); List changes = cleaner.cleanup(preset, entry); unsuccessfulRenames = cleaner.getUnsuccessfulRenames(); diff --git a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java index 5c1c7a570195..ab2a817742a9 100644 --- a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java @@ -54,6 +54,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; import net.sf.jabref.specialfields.Quality; @@ -321,7 +322,8 @@ private NamedCompound updateKeywords(List entries, Set keyword keywords.addAll(keywordsToAdd); // put keywords back - Optional change = entry.putKeywords(keywords); + Optional change = entry.putKeywords(keywords, + Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); if (change.isPresent()) { ce.addEdit(new UndoableFieldChange(change.get())); } diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 95ee322e314b..ef51e8324553 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -96,6 +96,7 @@ import net.sf.jabref.logic.autocompleter.AutoCompleter; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.search.SearchQueryHighlightListener; @@ -592,7 +593,8 @@ public void updateSource() { public static String getSourceString(BibEntry entry, BibDatabaseMode type) throws IOException { StringWriter stringWriter = new StringWriter(200); - LatexFieldFormatter formatter = LatexFieldFormatter.buildIgnoreHashes(); + LatexFieldFormatter formatter = LatexFieldFormatter + .buildIgnoreHashes(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)); new BibEntryWriter(formatter, false).writeWithoutPrependedNewlines(entry, stringWriter, type); return stringWriter.getBuffer().toString(); @@ -813,7 +815,8 @@ private boolean storeSource() { String newValue = newEntry.getField(field); if (!Objects.equals(oldValue, newValue)) { // Test if the field is legally set. - new LatexFieldFormatter().format(newValue, field); + new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)) + .format(newValue, field); compound.addEdit(new UndoableFieldChange(entry, field, oldValue, newValue)); entry.setField(field, newValue); @@ -1167,7 +1170,8 @@ public void actionPerformed(ActionEvent event) { // properly formatted. If that happens, the field // is not stored and the textarea turns red. if (toSet != null) { - new LatexFieldFormatter().format(toSet, fieldEditor.getFieldName()); + new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)) + .format(toSet, fieldEditor.getFieldName()); } String oldValue = entry.getField(fieldEditor.getFieldName()); @@ -1362,7 +1366,8 @@ public void actionPerformed(ActionEvent e) { } } - LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry); + LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry, + Globals.prefs); // Store undo information: panel.getUndoManager().addEdit(new UndoableKeyChange(panel.getDatabase(), entry, (String) oldValue, entry.getCiteKey())); diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index 9581d91a74f0..186b9054976d 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -45,6 +45,7 @@ import net.sf.jabref.gui.fieldeditors.FieldEditor; import net.sf.jabref.gui.mergeentries.MergeEntryDOIDialog; import net.sf.jabref.gui.undo.UndoableFieldChange; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.journals.JournalAbbreviationRepository; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLUtil; @@ -93,7 +94,8 @@ public static Optional getJournalExtraComponent(JabRefFrame frame, B button.setToolTipText(ABBREVIATION_TOOLTIP_TEXT); button.addActionListener(actionEvent -> { String text = editor.getText(); - JournalAbbreviationRepository abbreviationRepository = Globals.journalAbbreviationLoader.getRepository(); + JournalAbbreviationRepository abbreviationRepository = Globals.journalAbbreviationLoader + .getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)); if (abbreviationRepository.isKnownName(text)) { String s = abbreviationRepository.getNextAbbreviation(text).orElse(text); diff --git a/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java b/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java index 6df4e75a6abd..bef252b3c066 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportAction.java @@ -59,7 +59,7 @@ public InternalExportAction(JabRefFrame frame, boolean selectedOnly) { @Override public void actionPerformed(ActionEvent e) { - ExportFormats.initAllExports(); + ExportFormats.initAllExports(Globals.prefs.customExports.getCustomExportFormats(Globals.prefs)); JFileChooser fc = ExportAction .createExportFileChooser(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY)); fc.showSaveDialog(frame); diff --git a/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java index d2c8bae31b60..6d9e228ebb8d 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java @@ -91,43 +91,43 @@ public ExportCustomizationDialog(final JabRefFrame frame) { if (ecd.okPressed()) { List newFormat = Arrays.asList(ecd.name(), ecd.layoutFile(), ecd.extension()); Globals.prefs.customExports.addFormat(newFormat); - Globals.prefs.customExports.store(); + Globals.prefs.customExports.store(Globals.prefs); } }); JButton modify = new JButton(Localization.lang("Modify")); modify.addActionListener(e -> { - int row = table.getSelectedRow(); - if (row == -1) { - return; - } - List old = Globals.prefs.customExports.getSortedList().get(row); - CustomExportDialog ecd = new CustomExportDialog(frame, old.get(0), old.get(1), old.get(2)); - ecd.setVisible(true); // ecd.show(); -> deprecated since 1.5 - if (ecd.okPressed()) { - old.set(0, ecd.name()); - old.set(1, ecd.layoutFile()); - old.set(2, ecd.extension()); - table.revalidate(); - table.repaint(); - Globals.prefs.customExports.store(); - } + int row = table.getSelectedRow(); + if (row == -1) { + return; + } + List old = Globals.prefs.customExports.getSortedList().get(row); + CustomExportDialog ecd = new CustomExportDialog(frame, old.get(0), old.get(1), old.get(2)); + ecd.setVisible(true); // ecd.show(); -> deprecated since 1.5 + if (ecd.okPressed()) { + old.set(0, ecd.name()); + old.set(1, ecd.layoutFile()); + old.set(2, ecd.extension()); + table.revalidate(); + table.repaint(); + Globals.prefs.customExports.store(Globals.prefs); + } }); JButton remove = new JButton(Localization.lang("Remove")); remove.addActionListener(e -> { - int[] rows = table.getSelectedRows(); - if (rows.length == 0) { - return; - } - List> entries = new ArrayList<>(); - for (int i = 0; i < rows.length; i++) { - entries.add(Globals.prefs.customExports.getSortedList().get(rows[i])); - } - for (List list : entries) { - Globals.prefs.customExports.remove(list); - } - Globals.prefs.customExports.store(); + int[] rows = table.getSelectedRows(); + if (rows.length == 0) { + return; + } + List> entries = new ArrayList<>(); + for (int i = 0; i < rows.length; i++) { + entries.add(Globals.prefs.customExports.getSortedList().get(rows[i])); + } + for (List list : entries) { + Globals.prefs.customExports.remove(list); + } + Globals.prefs.customExports.store(Globals.prefs); }); Action closeAction = new AbstractAction() { diff --git a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java index 335f1470d106..8f658a05a17b 100644 --- a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java @@ -94,7 +94,8 @@ public void actionPerformed(ActionEvent e) { try { GroupTreeNode autoGroupsRoot = GroupTreeNode.fromGroup( - new ExplicitGroup(Localization.lang("Automatically created groups"), GroupHierarchyType.INCLUDING)); + new ExplicitGroup(Localization.lang("Automatically created groups"), + GroupHierarchyType.INCLUDING, Globals.prefs)); Set hs; String fieldText = field.getText(); if (keywords.isSelected()) { @@ -120,7 +121,7 @@ public void actionPerformed(ActionEvent e) { for (String keyword : hs) { KeywordGroup group = new KeywordGroup(keyword, fieldText, keyword, false, false, - GroupHierarchyType.INDEPENDENT); + GroupHierarchyType.INDEPENDENT, Globals.prefs); autoGroupsRoot.addChild(GroupTreeNode.fromGroup(group)); } diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index a5aa095174d2..18932a7d4b35 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -279,14 +279,14 @@ public void actionPerformed(ActionEvent e) { isOkPressed = true; try { if (explicitRadioButton.isSelected()) { - resultingGroup = new ExplicitGroup(nameField.getText().trim(), getContext()); + resultingGroup = new ExplicitGroup(nameField.getText().trim(), getContext(), Globals.prefs); } else if (keywordsRadioButton.isSelected()) { // regex is correct, otherwise OK would have been disabled // therefore I don't catch anything here resultingGroup = new KeywordGroup(nameField.getText().trim(), keywordGroupSearchField.getText().trim(), keywordGroupSearchTerm.getText().trim(), keywordGroupCaseSensitive.isSelected(), keywordGroupRegExp .isSelected(), - getContext()); + getContext(), Globals.prefs); } else if (searchRadioButton.isSelected()) { try { // regex is correct, otherwise OK would have been @@ -317,7 +317,7 @@ public void actionPerformed(ActionEvent e) { searchGroupCaseSensitive.addItemListener(itemListener); // configure for current type - if (editedGroup != null && editedGroup.getClass() == KeywordGroup.class) { + if ((editedGroup != null) && (editedGroup.getClass() == KeywordGroup.class)) { KeywordGroup group = (KeywordGroup) editedGroup; nameField.setText(group.getName()); keywordGroupSearchField.setText(group.getSearchField()); @@ -326,7 +326,7 @@ public void actionPerformed(ActionEvent e) { keywordGroupRegExp.setSelected(group.isRegExp()); keywordsRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); - } else if (editedGroup != null && editedGroup.getClass() == SearchGroup.class) { + } else if ((editedGroup != null) && (editedGroup.getClass() == SearchGroup.class)) { SearchGroup group = (SearchGroup) editedGroup; nameField.setText(group.getName()); searchGroupSearchExpression.setText(group.getSearchExpression()); @@ -334,7 +334,7 @@ public void actionPerformed(ActionEvent e) { searchGroupRegExp.setSelected(group.isRegExp()); searchRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); - } else if (editedGroup != null && editedGroup.getClass() == ExplicitGroup.class) { + } else if ((editedGroup != null) && (editedGroup.getClass() == ExplicitGroup.class)) { nameField.setText(editedGroup.getName()); explicitRadioButton.setSelected(true); setContext(editedGroup.getHierarchicalContext()); diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java index 1d2706592eef..99d2e65b8866 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -191,7 +191,7 @@ public String getText() { sb.append(group.getName()); if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_NUMBER_OF_ELEMENTS) - && JabRefGUI.getMainFrame() != null) { + && (JabRefGUI.getMainFrame() != null)) { BasePanel currentBasePanel = JabRefGUI.getMainFrame().getCurrentBasePanel(); if (currentBasePanel != null) { sb.append(" [").append(node.numberOfHits(currentBasePanel.getDatabase().getEntries())).append(']'); @@ -202,7 +202,9 @@ public String getText() { } public String getDescription() { - return "" + node.getGroup().getShortDescription() + ""; + return "" + + node.getGroup().getShortDescription(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_DYNAMIC)) + + ""; } public Icon getIcon() { diff --git a/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java b/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java index ffebc4c97766..ac94c7899d43 100644 --- a/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java +++ b/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java @@ -21,6 +21,7 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; @@ -52,7 +53,9 @@ public void run() { } UndoableAbbreviator undoableAbbreviator = new UndoableAbbreviator( - Globals.journalAbbreviationLoader.getRepository(), iso); + Globals.journalAbbreviationLoader + .getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)), + iso); NamedCompound ce = new NamedCompound(Localization.lang("Abbreviate journal names")); int count = 0; diff --git a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java index 3cd0c8e41242..4fc7f667a02e 100644 --- a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java +++ b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java @@ -66,6 +66,7 @@ import net.sf.jabref.gui.net.MonitoredURLDownload; import net.sf.jabref.logic.journals.Abbreviation; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.preferences.JabRefPreferences; @@ -185,7 +186,9 @@ public ManageJournalsPanel(final JabRefFrame frame) { viewBuiltin.addActionListener(e -> { JTable table = new JTable(JournalAbbreviationsUtil - .getTableModel(Globals.journalAbbreviationLoader.getRepository().getAbbreviations())); + .getTableModel(Globals.journalAbbreviationLoader + .getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)) + .getAbbreviations())); JScrollPane pane = new JScrollPane(table); JOptionPane.showMessageDialog(null, pane, Localization.lang("Journal list preview"), JOptionPane.INFORMATION_MESSAGE); @@ -392,7 +395,7 @@ private void storeSettings() { Globals.prefs.putStringList(JabRefPreferences.EXTERNAL_JOURNAL_LISTS, extFiles); // Update journal abbreviation loader - Globals.journalAbbreviationLoader.update(Globals.prefs); + Globals.journalAbbreviationLoader.update(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)); } diff --git a/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java b/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java index 8d12b4b983b4..28b5a3a505b6 100644 --- a/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java +++ b/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java @@ -21,6 +21,7 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; @@ -50,7 +51,8 @@ public void run() { } UndoableUnabbreviator undoableAbbreviator = new UndoableUnabbreviator( - Globals.journalAbbreviationLoader.getRepository()); + Globals.journalAbbreviationLoader + .getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs))); NamedCompound ce = new NamedCompound(Localization.lang("Unabbreviate journal names")); int count = 0; diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java index 2e72afc14aff..f1a96fe418bd 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java @@ -245,7 +245,7 @@ protected GlobalLabelPattern getLabelPatternAsGlobalLabelPattern() { } public DatabaseLabelPattern getLabelPatternAsDatabaseLabelPattern() { - DatabaseLabelPattern res = new DatabaseLabelPattern(); + DatabaseLabelPattern res = new DatabaseLabelPattern(Globals.prefs); fillPatternUsingPanelData(res); return res; } diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java b/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java index 93031edd9a25..930b0e770ef0 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/SearchFixDuplicateLabels.java @@ -22,6 +22,7 @@ import javax.swing.JCheckBox; +import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.undo.UndoableKeyChange; @@ -109,7 +110,8 @@ public void update() { NamedCompound ce = new NamedCompound(Localization.lang("Resolve duplicate BibTeX keys")); for (BibEntry entry : toGenerateFor) { String oldKey = entry.getCiteKey(); - LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry); + LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry, + Globals.prefs); ce.addEdit(new UndoableKeyChange(panel.getDatabase(), entry, oldKey, entry.getCiteKey())); } ce.end(); diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java index 7bdf6b01caae..7d15dd53d13a 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntries.java @@ -46,6 +46,7 @@ import net.sf.jabref.gui.PreviewPanel; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.formatter.casechanger.SentenceCaseFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.strings.DiffHighlighting; @@ -452,7 +453,8 @@ private void updateAll() { // Update the BibTeX source view StringWriter writer = new StringWriter(); try { - new BibEntryWriter(new LatexFieldFormatter(), false).write(mergedEntry, writer, databaseType); + new BibEntryWriter(new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)), + false).write(mergedEntry, writer, databaseType); } catch (IOException ex) { LOGGER.error("Error in entry", ex); } diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java index c1d084a56816..891540870406 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java @@ -126,7 +126,8 @@ private OpenOfficePanel() { update = new JButton(IconTheme.JabRefIcon.REFRESH.getSmallIcon()); update.setToolTipText(Localization.lang("Sync OpenOffice/LibreOffice bibliography")); preferences = new OpenOfficePreferences(Globals.prefs); - loader = new StyleLoader(preferences, Globals.journalAbbreviationLoader, Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(preferences, Globals.prefs, Globals.journalAbbreviationLoader, + Globals.prefs.getDefaultEncoding()); } public static OpenOfficePanel getInstance() { diff --git a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java index d324fdc27093..4107bb59e613 100644 --- a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java +++ b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java @@ -123,6 +123,7 @@ import net.sf.jabref.importer.fileformat.FreeCiteImporter; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.UpdateField; import net.sf.jabref.model.EntryTypes; @@ -476,7 +477,7 @@ private void insertTextForTag(boolean overrideField) { entry.setField(fieldName, old.get() + " and " + txt); } else if ("keywords".equals(fieldName)) { // Add keyword - entry.addKeyword(txt); + entry.addKeyword(txt, Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); } else { entry.setField(fieldName, old.get() + txt); } @@ -537,7 +538,9 @@ private boolean parseWithFreeCiteAndAddEntries() { private void updateSourceView() { StringWriter sw = new StringWriter(200); try { - new BibEntryWriter(new LatexFieldFormatter(), false).write(entry, sw, frame.getCurrentBasePanel().getBibDatabaseContext().getMode()); + new BibEntryWriter(new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)), + false).write(entry, sw, + frame.getCurrentBasePanel().getBibDatabaseContext().getMode()); sourcePreview.setText(sw.getBuffer().toString()); } catch (IOException ex) { LOGGER.error("Error in entry" + ": " + ex.getMessage(), ex); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java index c9b146bfc03a..b2b78cfbd872 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java @@ -29,6 +29,7 @@ import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.remote.JabRefMessageHandler; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.remote.RemotePreferences; import net.sf.jabref.logic.remote.RemoteUtil; @@ -44,7 +45,6 @@ class AdvancedTab extends JPanel implements PrefsTab { private final JCheckBox useIEEEAbrv; private final JTextField remoteServerPort; - private final JCheckBox useConvertToEquation; private final JCheckBox useCaseKeeperOnSearch; private final JCheckBox useUnitFormatterOnSearch; private final RemotePreferences remotePreferences; @@ -57,7 +57,6 @@ public AdvancedTab(JabRefPreferences prefs) { useRemoteServer = new JCheckBox(Localization.lang("Listen for remote operation on port") + ':'); useIEEEAbrv = new JCheckBox(Localization.lang("Use IEEE LaTeX abbreviations")); remoteServerPort = new JTextField(); - useConvertToEquation = new JCheckBox(Localization.lang("Prefer converting subscripts and superscripts to equations rather than text")); useCaseKeeperOnSearch = new JCheckBox(Localization.lang("Add {} to specified title words on search to keep the correct case")); useUnitFormatterOnSearch = new JCheckBox(Localization.lang("Format units by adding non-breaking separators and keeping the correct case on search")); @@ -95,9 +94,6 @@ public AdvancedTab(JabRefPreferences prefs) { builder.nextLine(); builder.appendSeparator(Localization.lang("Import conversions")); builder.nextLine(); - builder.append(new JPanel()); - builder.append(useConvertToEquation); - builder.nextLine(); builder.append(pan); builder.append(useCaseKeeperOnSearch); builder.nextLine(); @@ -116,7 +112,6 @@ public void setValues() { useRemoteServer.setSelected(remotePreferences.useRemoteServer()); remoteServerPort.setText(String.valueOf(remotePreferences.getPort())); useIEEEAbrv.setSelected(Globals.prefs.getBoolean(JabRefPreferences.USE_IEEE_ABRV)); - useConvertToEquation.setSelected(Globals.prefs.getBoolean(JabRefPreferences.USE_CONVERT_TO_EQUATION)); useCaseKeeperOnSearch.setSelected(Globals.prefs.getBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH)); useUnitFormatterOnSearch.setSelected(Globals.prefs.getBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH)); } @@ -125,11 +120,10 @@ public void setValues() { public void storeSettings() { if (preferences.getBoolean(JabRefPreferences.USE_IEEE_ABRV) != useIEEEAbrv.isSelected()) { preferences.putBoolean(JabRefPreferences.USE_IEEE_ABRV, useIEEEAbrv.isSelected()); - Globals.journalAbbreviationLoader.update(preferences); + Globals.journalAbbreviationLoader.update(JournalAbbreviationPreferences.fromPreferences(preferences)); } storeRemoteSettings(); - preferences.putBoolean(JabRefPreferences.USE_CONVERT_TO_EQUATION, useConvertToEquation.isSelected()); preferences.putBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH, useCaseKeeperOnSearch.isSelected()); preferences.putBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH, useUnitFormatterOnSearch.isSelected()); } diff --git a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java index c3b33ac699e7..5d167a3b9a16 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/PreferencesDialog.java @@ -236,7 +236,7 @@ public PreferencesDialog(JabRefFrame parent) { private void updateAfterPreferenceChanges() { setValues(); - ExportFormats.initAllExports(); + ExportFormats.initAllExports(Globals.prefs.customExports.getCustomExportFormats(Globals.prefs)); frame.removeCachedEntryEditors(); Globals.prefs.updateEntryEditorTabList(); } diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java index bf70ae85306e..70ee52724a33 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TablePrefsTab.java @@ -31,6 +31,7 @@ import javax.swing.JTable; import javax.swing.JTextField; +import net.sf.jabref.Globals; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -300,7 +301,7 @@ public void storeSettings() { } if (!Objects.equals(oldVal, newVal)) { prefs.put(JabRefPreferences.NUMERIC_FIELDS, newVal); - InternalBibtexFields.setNumericFieldsFromPrefs(); + InternalBibtexFields.setNumericFields(Globals.prefs.getStringList(JabRefPreferences.NUMERIC_FIELDS)); } } diff --git a/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java b/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java index 5f93c7ea2ee8..aa90899d5727 100644 --- a/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java +++ b/src/main/java/net/sf/jabref/gui/worker/SendAsEMailAction.java @@ -24,11 +24,13 @@ import java.util.ArrayList; import java.util.List; +import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; @@ -79,7 +81,8 @@ public void run() { List bes = panel.getSelectedEntries(); // write the entries using sw, which is used later to form the email content - BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new LatexFieldFormatter(), true); + BibEntryWriter bibtexEntryWriter = new BibEntryWriter( + new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)), true); for (BibEntry entry : bes) { try { diff --git a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java index 8f83a6618a6f..61b8c67cd425 100644 --- a/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java +++ b/src/main/java/net/sf/jabref/importer/AppendDatabaseAction.java @@ -168,7 +168,7 @@ private static void mergeFromBibtex(JabRefFrame frame, BasePanel panel, ParserRe // create a dummy group ExplicitGroup group = null; try { - group = new ExplicitGroup("Imported", GroupHierarchyType.INDEPENDENT); + group = new ExplicitGroup("Imported", GroupHierarchyType.INDEPENDENT, Globals.prefs); } catch (ParseException e) { LOGGER.error(e); } diff --git a/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java b/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java index 485cc674e927..49b2efd4add1 100644 --- a/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java +++ b/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Optional; +import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; @@ -119,7 +120,7 @@ private void addEntryDataFromPDDocumentInformation(File pdfFile, BibEntry entry) */ private void addEntryDataFromXMP(File aFile, BibEntry entry) { try { - List entrys = XMPUtil.readXMP(aFile.getAbsoluteFile()); + List entrys = XMPUtil.readXMP(aFile.getAbsoluteFile(), Globals.prefs); addEntrysToEntry(entry, entrys); } catch (IOException e) { // no canceling here, just no data added. diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java index 6317ea3733c4..4d019069515e 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java @@ -143,7 +143,7 @@ public boolean processQueryGetPreview(String query, FetcherPreviewDialog preview try { URLDownload dl = new URLDownload(address); - String page = dl.downloadToString(); + String page = dl.downloadToString(Globals.prefs.getDefaultEncoding()); int hits = getNumberOfHits(page, RESULTS_FOUND_PATTERN, ACMPortalFetcher.HITS_PATTERN); @@ -351,7 +351,7 @@ private static Optional downloadEntryBibTeX(String id, boolean downloa // get abstract if (downloadAbstract) { URLDownload dl = new URLDownload(ACMPortalFetcher.START_URL + ACMPortalFetcher.ABSTRACT_URL + id); - String page = dl.downloadToString(); + String page = dl.downloadToString(Globals.prefs.getDefaultEncoding()); Matcher absM = ACMPortalFetcher.ABSTRACT_PATTERN.matcher(page); if (absM.find()) { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java index 0b6a3f0a2e3b..29d9e8aa8f43 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java @@ -25,6 +25,7 @@ import javax.swing.JPanel; +import net.sf.jabref.Globals; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -127,7 +128,7 @@ private List getCitations(String query) throws IOException { } private static String getCitationsFromUrl(String urlQuery, List ids) throws IOException { - String cont = new URLDownload(urlQuery).downloadToString(); + String cont = new URLDownload(urlQuery).downloadToString(Globals.prefs.getDefaultEncoding()); Matcher m = CiteSeerXFetcher.CITE_LINK_PATTERN.matcher(cont); while (m.find()) { ids.add(CiteSeerXFetcher.URL_START + m.group(1)); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java index 119e5d8a7812..320b47b07e56 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java @@ -24,6 +24,7 @@ import javax.swing.JPanel; +import net.sf.jabref.Globals; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -74,7 +75,7 @@ public boolean processQuery(String newQuery, ImportInspector inspector, String address = makeSearchURL(); URLDownload dl = new URLDownload(address); - String page = dl.downloadToString(); + String page = dl.downloadToString(Globals.prefs.getDefaultEncoding()); String[] lines = page.split("\n"); List bibtexUrlList = new ArrayList<>(); @@ -100,7 +101,8 @@ public boolean processQuery(String newQuery, ImportInspector inspector, break; } - final String bibtexHTMLPage = new URLDownload(urlStr).downloadToString(); + final String bibtexHTMLPage = new URLDownload(urlStr) + .downloadToString(Globals.prefs.getDefaultEncoding()); final String[] htmlLines = bibtexHTMLPage.split("\n"); @@ -114,7 +116,8 @@ public boolean processQuery(String newQuery, ImportInspector inspector, // we do not access dblp.uni-trier.de as they will complain bibtexUrl = bibtexUrl.replace("dblp.uni-trier.de", "www.dblp.org"); - final String bibtexPage = new URLDownload(bibtexUrl).downloadToString(); + final String bibtexPage = new URLDownload(bibtexUrl) + .downloadToString(Globals.prefs.getDefaultEncoding()); Collection bibtexEntries = BibtexParser.fromString(bibtexPage); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java index 6f22e69a30dd..2a1a26934aeb 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java @@ -32,6 +32,7 @@ import javax.swing.JLabel; import javax.swing.JPanel; +import net.sf.jabref.Globals; import net.sf.jabref.gui.FetcherPreviewDialog; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; @@ -173,9 +174,10 @@ public void stopFetching() { private static void runConfig() throws IOException { try { - new URLDownload("http://scholar.google.com").downloadToString(); + new URLDownload("http://scholar.google.com").downloadToString(Globals.prefs.getDefaultEncoding()); //save("setting.html", ud.getStringContent()); - String settingsPage = new URLDownload(GoogleScholarFetcher.URL_SETTING).downloadToString(); + String settingsPage = new URLDownload(GoogleScholarFetcher.URL_SETTING) + .downloadToString(Globals.prefs.getDefaultEncoding()); // Get the form items and their values from the page: Map formItems = GoogleScholarFetcher.getFormElements(settingsPage); // Override the important ones: @@ -185,7 +187,7 @@ private static void runConfig() throws IOException { String request = formItems.entrySet().stream().map(Object::toString) .collect(Collectors.joining("&", GoogleScholarFetcher.URL_SETPREFS + "?", "&submit=")); // Download the URL to set preferences: - new URLDownload(request).downloadToString(); + new URLDownload(request).downloadToString(Globals.prefs.getDefaultEncoding()); } catch (UnsupportedEncodingException ex) { LOGGER.error("Unsupported encoding.", ex); @@ -216,7 +218,7 @@ private Map getCitations(String query) throws IOException { } private String getCitationsFromUrl(String urlQuery, Map ids) throws IOException { - String cont = new URLDownload(urlQuery).downloadToString(); + String cont = new URLDownload(urlQuery).downloadToString(Globals.prefs.getDefaultEncoding()); Matcher m = GoogleScholarFetcher.BIBTEX_LINK_PATTERN.matcher(cont); int lastRegionStart = 0; @@ -263,7 +265,8 @@ private String getCitationsFromUrl(String urlQuery, Map ids) thr private BibEntry downloadEntry(String link) throws IOException { try { - String s = new URLDownload(GoogleScholarFetcher.URL_START + link).downloadToString(); + String s = new URLDownload(GoogleScholarFetcher.URL_START + link) + .downloadToString(Globals.prefs.getDefaultEncoding()); BibtexParser bp = new BibtexParser(new StringReader(s)); ParserResult pr = bp.parse(); if ((pr != null) && (pr.getDatabase() != null)) { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index 7b5617d28d4e..9d8bae307bf0 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -44,6 +44,7 @@ import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; @@ -73,11 +74,9 @@ public class IEEEXploreFetcher implements EntryFetcher { private static final Pattern SUB_DETECTION_1 = Pattern.compile("/sub ([^/]+)/"); private static final Pattern SUB_DETECTION_2 = Pattern.compile("\\(sub\\)([^(]+)\\(/sub\\)"); private static final String SUB_TEXT_RESULT = "\\\\textsubscript\\{$1\\}"; - private static final String SUB_EQ_RESULT = "\\$_\\{$1\\}\\$"; private static final Pattern SUPER_DETECTION_1 = Pattern.compile("/sup ([^/]+)/"); private static final Pattern SUPER_DETECTION_2 = Pattern.compile("\\(sup\\)([^(]+)\\(/sup\\)"); private static final String SUPER_TEXT_RESULT = "\\\\textsuperscript\\{$1\\}"; - private static final String SUPER_EQ_RESULT = "\\$\\^\\{$1\\}\\$"; private final ProtectTermsFormatter protectTermsFormatter = new ProtectTermsFormatter(); private final UnitsToLatexFormatter unitsToLatexFormatter = new UnitsToLatexFormatter(); @@ -156,7 +155,8 @@ public boolean processQuery(String query, ImportInspector dialog, OutputPrinter } //fetch the raw Bibtex results from IEEEXplore - String bibtexPage = new URLDownload(createBibtexQueryURL(searchResultsJson)).downloadToString(); + String bibtexPage = new URLDownload(createBibtexQueryURL(searchResultsJson)) + .downloadToString(Globals.prefs.getDefaultEncoding()); //preprocess the result (eg. convert HTML escaped characters to latex and do other formatting not performed by BibtexParser) bibtexPage = preprocessBibtexResultsPage(bibtexPage); @@ -279,17 +279,10 @@ private BibEntry cleanup(BibEntry entry) { // Replace general expressions title = title.replaceAll("/[sS]pl ([^/]+)/", "\\$\\\\$1\\$"); // Deal with subscripts and superscripts - if (Globals.prefs.getBoolean(JabRefPreferences.USE_CONVERT_TO_EQUATION)) { - title = SUPER_DETECTION_1.matcher(title).replaceAll(SUPER_EQ_RESULT); - title = SUB_DETECTION_1.matcher(title).replaceAll(SUB_EQ_RESULT); - title = SUPER_DETECTION_2.matcher(title).replaceAll(SUPER_EQ_RESULT); - title = SUB_DETECTION_2.matcher(title).replaceAll(SUB_EQ_RESULT); - } else { - title = SUPER_DETECTION_1.matcher(title).replaceAll(SUPER_TEXT_RESULT); - title = SUB_DETECTION_1.matcher(title).replaceAll(SUB_TEXT_RESULT); - title = SUPER_DETECTION_2.matcher(title).replaceAll(SUPER_TEXT_RESULT); - title = SUB_DETECTION_2.matcher(title).replaceAll(SUB_TEXT_RESULT); - } + title = SUPER_DETECTION_1.matcher(title).replaceAll(SUPER_TEXT_RESULT); + title = SUB_DETECTION_1.matcher(title).replaceAll(SUB_TEXT_RESULT); + title = SUPER_DETECTION_2.matcher(title).replaceAll(SUPER_TEXT_RESULT); + title = SUB_DETECTION_2.matcher(title).replaceAll(SUB_TEXT_RESULT); // Replace \infin with \infty title = title.replaceAll("\\\\infin", "\\\\infty"); @@ -443,7 +436,10 @@ private BibEntry cleanup(BibEntry entry) { fullName = fullName.trim(); if (Globals.prefs.getBoolean(JabRefPreferences.USE_IEEE_ABRV)) { - fullName = abbreviationLoader.getRepository().getMedlineAbbreviation(fullName).orElse(fullName); + fullName = abbreviationLoader + .getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)) + .getMedlineAbbreviation(fullName) + .orElse(fullName); } } if ("inproceedings".equals(type)) { @@ -498,17 +494,10 @@ private BibEntry cleanup(BibEntry entry) { // Replace general expressions abstr = abstr.replaceAll("/[sS]pl ([^/]+)/", "\\$\\\\$1\\$"); // Deal with subscripts and superscripts - if (Globals.prefs.getBoolean(JabRefPreferences.USE_CONVERT_TO_EQUATION)) { - abstr = SUPER_DETECTION_1.matcher(abstr).replaceAll(SUPER_EQ_RESULT); - abstr = SUB_DETECTION_1.matcher(abstr).replaceAll(SUB_EQ_RESULT); - abstr = SUPER_DETECTION_2.matcher(abstr).replaceAll(SUPER_EQ_RESULT); - abstr = SUB_DETECTION_2.matcher(abstr).replaceAll(SUB_EQ_RESULT); - } else { - abstr = SUPER_DETECTION_1.matcher(abstr).replaceAll(SUPER_TEXT_RESULT); - abstr = SUB_DETECTION_1.matcher(abstr).replaceAll(SUB_TEXT_RESULT); - abstr = SUPER_DETECTION_2.matcher(abstr).replaceAll(SUPER_TEXT_RESULT); - abstr = SUB_DETECTION_2.matcher(abstr).replaceAll(SUB_TEXT_RESULT); - } + abstr = SUPER_DETECTION_1.matcher(abstr).replaceAll(SUPER_TEXT_RESULT); + abstr = SUB_DETECTION_1.matcher(abstr).replaceAll(SUB_TEXT_RESULT); + abstr = SUPER_DETECTION_2.matcher(abstr).replaceAll(SUPER_TEXT_RESULT); + abstr = SUB_DETECTION_2.matcher(abstr).replaceAll(SUB_TEXT_RESULT); // Replace \infin with \infty abstr = abstr.replace("\\infin", "\\infty"); // Write back diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java index 54478da27344..6fc7724a6252 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java @@ -26,6 +26,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; +import net.sf.jabref.Globals; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; @@ -135,7 +136,7 @@ private static List getCitations(String query) throws IOException { } private static String getCitationsFromUrl(String urlQuery, List ids) throws IOException { - String cont = new URLDownload(urlQuery).downloadToString(); + String cont = new URLDownload(urlQuery).downloadToString(Globals.prefs.getDefaultEncoding()); Matcher m = ScienceDirectFetcher.LINK_PATTERN.matcher(cont); if (m.find()) { while (m.find()) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 253bf298601e..9cfd91af080c 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -33,6 +33,7 @@ import net.sf.jabref.MetaData; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.bibtex.FieldContentParser; +import net.sf.jabref.logic.bibtex.FieldContentParserPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.KeyCollisionException; @@ -43,6 +44,7 @@ import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -70,7 +72,8 @@ public class BibtexParser { private Map entryTypes; private boolean eof; private int line = 1; - private final FieldContentParser fieldContentParser = new FieldContentParser(); + private final FieldContentParser fieldContentParser = new FieldContentParser( + FieldContentParserPreferences.fromPreferences(Globals.prefs)); private ParserResult parserResult; private static final Integer LOOKAHEAD = 64; private final Deque pureTextFromFile = new LinkedList<>(); @@ -562,7 +565,7 @@ private void parseField(BibEntry entry) throws IOException { entry.setField(key, entry.getFieldOptional(key).get() + " and " + content); } else if ("keywords".equals(key)) { //multiple keywords fields should be combined to one - entry.addKeyword(content); + entry.addKeyword(content, Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); } } else { entry.setField(key, content); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index ae766615b393..445d248f21fc 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -213,7 +213,9 @@ public ParserResult importEntries(String text) { e.setType(type); // autogenerate label (BibTeX key) - LabelPatternUtil.makeLabel(JabRefGUI.getMainFrame().getCurrentBasePanel().getBibDatabaseContext().getMetaData(), JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabase(), e); + LabelPatternUtil.makeLabel( + JabRefGUI.getMainFrame().getCurrentBasePanel().getBibDatabaseContext().getMetaData(), + JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabase(), e, Globals.prefs); res.add(e); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java index 8bba5ec0a588..134501c69f47 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java @@ -20,8 +20,10 @@ import java.util.LinkedHashSet; import java.util.List; +import net.sf.jabref.Globals; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.MonthUtil; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -111,7 +113,7 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { keywordList.add(keywords.getString(i)); } } - entry.putKeywords(keywordList); + entry.putKeywords(keywordList, Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); } // Identifiers diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java index 9552dc4fbc8a..a3937b48c892 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfXmpImporter.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Objects; +import net.sf.jabref.Globals; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.xmp.XMPUtil; @@ -54,7 +55,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { Objects.requireNonNull(filePath); try { - return new ParserResult(XMPUtil.readXMP(filePath)); + return new ParserResult(XMPUtil.readXMP(filePath, Globals.prefs)); } catch (IOException exception) { return ParserResult.fromErrorMessage(exception.getLocalizedMessage()); } @@ -75,7 +76,7 @@ protected boolean isRecognizedFormat(BufferedReader reader) throws IOException { @Override public boolean isRecognizedFormat(Path filePath, Charset defaultEncoding) throws IOException { Objects.requireNonNull(filePath); - return XMPUtil.hasMetadata(filePath); + return XMPUtil.hasMetadata(filePath, Globals.prefs); } @Override diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index d74ed3dfc018..31e7881705e8 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -32,9 +32,11 @@ import java.util.List; import java.util.Objects; +import net.sf.jabref.Globals; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.IdGenerator; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -350,7 +352,8 @@ private void parseAdditionalFields(BibEntry be, boolean multilineUrlFieldAllowed if ("Keywords".equals(keyword)) { String content = readMultipleLines(in); String[] keywords = content.split("[,;]"); - be.addKeywords(new LinkedHashSet<>(Arrays.asList(keywords))); + be.addKeywords(new LinkedHashSet<>(Arrays.asList(keywords)), + Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); // parse JEL field } else if ("JEL".equals(keyword)) { be.setField("jel", readMultipleLines(in)); diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java index c0694feae1e6..5c1891e5bf3d 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompletePreferences.java @@ -19,6 +19,7 @@ import java.util.Map; import java.util.Objects; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.preferences.JabRefPreferences; public class AutoCompletePreferences { @@ -98,4 +99,8 @@ public String getCompleteNamesAsString() { public void setCompleteNames(String value) { preferences.put(PREF_COMPLETE_FIELDS, value); } + + public JournalAbbreviationPreferences getJournalAbbreviationPreferences() { + return JournalAbbreviationPreferences.fromPreferences(preferences); + } } \ No newline at end of file diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java index 9e9f4f7d2c4f..1089cc36eeea 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java @@ -32,6 +32,7 @@ public class AutoCompleterFactory { private final AutoCompletePreferences preferences; private final JournalAbbreviationLoader abbreviationLoader; + public AutoCompleterFactory(AutoCompletePreferences preferences, JournalAbbreviationLoader abbreviationLoader) { this.preferences = Objects.requireNonNull(preferences); this.abbreviationLoader = Objects.requireNonNull(abbreviationLoader); diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java b/src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java index 51cc5afb1fd7..64cab011c0d8 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/JournalAutoCompleter.java @@ -22,14 +22,19 @@ import net.sf.jabref.logic.journals.Abbreviation; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; public class JournalAutoCompleter extends EntireFieldAutoCompleter { private final JournalAbbreviationLoader abbreviationLoader; + private final JournalAbbreviationPreferences journalAbbreviationPreferences; - JournalAutoCompleter(String fieldName, AutoCompletePreferences preferences, JournalAbbreviationLoader abbreviationLoader) { + + JournalAutoCompleter(String fieldName, AutoCompletePreferences preferences, + JournalAbbreviationLoader abbreviationLoader) { super(fieldName, preferences); this.abbreviationLoader = Objects.requireNonNull(abbreviationLoader); + this.journalAbbreviationPreferences = preferences.getJournalAbbreviationPreferences(); } @Override @@ -37,7 +42,8 @@ public List complete(String toComplete) { List completions = super.complete(toComplete); // Also return journal names in the journal abbreviation list - for (Abbreviation abbreviation : abbreviationLoader.getRepository().getAbbreviations()) { + for (Abbreviation abbreviation : abbreviationLoader + .getRepository(journalAbbreviationPreferences).getAbbreviations()) { if (abbreviation.getName().startsWith(toComplete)) { completions.add(abbreviation.getName()); } diff --git a/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java index e52c0be187b4..a363afc295f2 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java @@ -16,12 +16,9 @@ package net.sf.jabref.logic.bibtex; import java.util.HashSet; -import java.util.List; import java.util.regex.Pattern; -import net.sf.jabref.Globals; import net.sf.jabref.logic.util.strings.StringUtil; -import net.sf.jabref.preferences.JabRefPreferences; /** * This class provides the reformatting needed when reading BibTeX fields formatted @@ -34,14 +31,14 @@ public class FieldContentParser { // 's' matches a space, tab, new line, carriage return. private static final Pattern WHITESPACE = Pattern.compile("\\s+"); - public FieldContentParser() { + + public FieldContentParser(FieldContentParserPreferences prefs) { multiLineFields = new HashSet<>(); // the following two are also coded in net.sf.jabref.logic.bibtex.LatexFieldFormatter.format(String, String) multiLineFields.add("abstract"); multiLineFields.add("review"); // the file field should not be formatted, therefore we treat it as a multi line field - List nonWrappableFields = Globals.prefs.getStringList(JabRefPreferences.NON_WRAPPABLE_FIELDS); - multiLineFields.addAll(nonWrappableFields); + multiLineFields.addAll(prefs.getNonWrappableFields()); } /** diff --git a/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParserPreferences.java b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParserPreferences.java new file mode 100644 index 000000000000..486d25833406 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParserPreferences.java @@ -0,0 +1,30 @@ +package net.sf.jabref.logic.bibtex; + +import java.util.Collections; +import java.util.List; + +import net.sf.jabref.preferences.JabRefPreferences; + +public class FieldContentParserPreferences { + + private final List nonWrappableFields; + + + public FieldContentParserPreferences() { + // This constructor is only to allow an empty constructor in SavePreferences + this.nonWrappableFields = Collections.emptyList(); + } + + public FieldContentParserPreferences(List nonWrappableFields) { + this.nonWrappableFields = nonWrappableFields; + } + + public List getNonWrappableFields() { + return nonWrappableFields; + } + + public static FieldContentParserPreferences fromPreferences(JabRefPreferences jabRefPreferences) { + return new FieldContentParserPreferences( + jabRefPreferences.getStringList(JabRefPreferences.NON_WRAPPABLE_FIELDS)); + } +} diff --git a/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java index 347bdcbffe97..95e4e49b89d1 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatter.java @@ -21,7 +21,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.InternalBibtexFields; -import net.sf.jabref.preferences.JabRefPreferences; /** * Currently the only implementation of net.sf.jabref.exporter.FieldFormatter @@ -40,33 +39,24 @@ public class LatexFieldFormatter { private final boolean neverFailOnHashes; - private final boolean resolveStringsAllFields; - private final char valueDelimiterStartOfValue; - private final char valueDelimiterEndOfValue; - private final List doNotResolveStringsFors; - private final int lineLength; + private final LatexFieldFormatterPreferences prefs; private final FieldContentParser parser; - public LatexFieldFormatter() { - this(true); + public LatexFieldFormatter(LatexFieldFormatterPreferences prefs) { + this(true, prefs); } - private LatexFieldFormatter(boolean neverFailOnHashes) { + private LatexFieldFormatter(boolean neverFailOnHashes, LatexFieldFormatterPreferences prefs) { this.neverFailOnHashes = neverFailOnHashes; + this.prefs = prefs; - this.resolveStringsAllFields = Globals.prefs.getBoolean(JabRefPreferences.RESOLVE_STRINGS_ALL_FIELDS); - valueDelimiterStartOfValue = Globals.prefs.getValueDelimiters(0); - valueDelimiterEndOfValue = Globals.prefs.getValueDelimiters(1); - doNotResolveStringsFors = Globals.prefs.getStringList(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR); - lineLength = Globals.prefs.getInt(JabRefPreferences.LINE_LENGTH); - - parser = new FieldContentParser(); + parser = new FieldContentParser(prefs.getFieldContentParserPreferences()); } - public static LatexFieldFormatter buildIgnoreHashes() { - return new LatexFieldFormatter(true); + public static LatexFieldFormatter buildIgnoreHashes(LatexFieldFormatterPreferences prefs) { + return new LatexFieldFormatter(true, prefs); } /** @@ -81,7 +71,7 @@ public String format(String content, String fieldName) throws IllegalArgumentException { if (content == null) { - return valueDelimiterStartOfValue + String.valueOf(valueDelimiterEndOfValue); + return prefs.getValueDelimiterStartOfValue() + String.valueOf(prefs.getValueDelimiterEndOfValue()); } String result = content; @@ -172,9 +162,9 @@ private String formatAndResolveStrings(String content, String fieldName) { private boolean shouldResolveStrings(String fieldName) { boolean resolveStrings = true; - if (resolveStringsAllFields) { + if (prefs.isResolveStringsAllFields()) { // Resolve strings for all fields except some: - for (String exception : doNotResolveStringsFors) { + for (String exception : prefs.getDoNotResolveStringsFor()) { if (exception.equals(fieldName)) { resolveStrings = false; break; @@ -192,18 +182,18 @@ private String formatWithoutResolvingStrings(String content, String fieldName) { checkBraces(content); stringBuilder = new StringBuilder( - String.valueOf(valueDelimiterStartOfValue)); + String.valueOf(prefs.getValueDelimiterStartOfValue())); stringBuilder.append(parser.format(content, fieldName)); - stringBuilder.append(valueDelimiterEndOfValue); + stringBuilder.append(prefs.getValueDelimiterEndOfValue()); return stringBuilder.toString(); } private void writeText(String text, int startPos, int endPos) { - stringBuilder.append(valueDelimiterStartOfValue); + stringBuilder.append(prefs.getValueDelimiterStartOfValue()); boolean escape = false; boolean inCommandName = false; boolean inCommand = false; @@ -262,7 +252,7 @@ private void writeText(String text, int startPos, int endPos) { } escape = c == '\\'; } - stringBuilder.append(valueDelimiterEndOfValue); + stringBuilder.append(prefs.getValueDelimiterEndOfValue()); } private void writeStringLabel(String text, int startPos, int endPos, @@ -272,7 +262,7 @@ private void writeStringLabel(String text, int startPos, int endPos, } private void putIn(String s) { - stringBuilder.append(StringUtil.wrap(s, lineLength)); + stringBuilder.append(StringUtil.wrap(s, prefs.getLineLength())); } private static void checkBraces(String text) throws IllegalArgumentException { diff --git a/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterPreferences.java b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterPreferences.java new file mode 100644 index 000000000000..8342a18ff08c --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterPreferences.java @@ -0,0 +1,64 @@ +package net.sf.jabref.logic.bibtex; + +import java.util.Collections; +import java.util.List; + +import net.sf.jabref.preferences.JabRefPreferences; + +public class LatexFieldFormatterPreferences { + + private final boolean resolveStringsAllFields; + private final char valueDelimiterStartOfValue; + private final char valueDelimiterEndOfValue; + private final List doNotResolveStringsFor; + private final int lineLength; + private final FieldContentParserPreferences fieldContentParserPreferences; + + + public LatexFieldFormatterPreferences(boolean resolveStringsAllFields, char valueDelimiterStartOfValue, + char valueDelimiterEndOfValue, List doNotResolveStringsFor, int lineLength, + FieldContentParserPreferences fieldContentParserPreferences) { + this.resolveStringsAllFields = resolveStringsAllFields; + this.valueDelimiterStartOfValue = valueDelimiterStartOfValue; + this.valueDelimiterEndOfValue = valueDelimiterEndOfValue; + this.doNotResolveStringsFor = doNotResolveStringsFor; + this.lineLength = lineLength; + this.fieldContentParserPreferences = fieldContentParserPreferences; + } + + public LatexFieldFormatterPreferences() { + // This constructor is only to allow an empty constructor in SavePreferences + this(true, '{', '}', Collections.emptyList(), 0, new FieldContentParserPreferences()); + } + + public static LatexFieldFormatterPreferences fromPreferences(JabRefPreferences prefs) { + return new LatexFieldFormatterPreferences(prefs.getBoolean(JabRefPreferences.RESOLVE_STRINGS_ALL_FIELDS), + prefs.getValueDelimiters(0), prefs.getValueDelimiters(1), + prefs.getStringList(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR), + prefs.getInt(JabRefPreferences.LINE_LENGTH), FieldContentParserPreferences.fromPreferences(prefs)); + } + + public boolean isResolveStringsAllFields() { + return resolveStringsAllFields; + } + + public char getValueDelimiterStartOfValue() { + return valueDelimiterStartOfValue; + } + + public char getValueDelimiterEndOfValue() { + return valueDelimiterEndOfValue; + } + + public List getDoNotResolveStringsFor() { + return doNotResolveStringsFor; + } + + public int getLineLength() { + return lineLength; + } + + public FieldContentParserPreferences getFieldContentParserPreferences() { + return fieldContentParserPreferences; + } +} diff --git a/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java index 6ea66ddb816e..e4d41f28f7f2 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java @@ -48,15 +48,6 @@ public class FieldComparator implements Comparator { private static final Collator COLLATOR = getCollator(); - private static Collator getCollator() { - try { - return new RuleBasedCollator( - ((RuleBasedCollator) Collator.getInstance()).getRules().replace("<'\u005f'", "<' '<'\u005f'")); - } catch (ParseException e) { - return Collator.getInstance(); - } - } - enum FieldType { NAME, TYPE, YEAR, MONTH, OTHER } @@ -89,6 +80,19 @@ public FieldComparator(String field, boolean reversed) { } } + public FieldComparator(SaveOrderConfig.SortCriterion sortCriterion) { + this(sortCriterion.field, sortCriterion.descending); + } + + private static Collator getCollator() { + try { + return new RuleBasedCollator( + ((RuleBasedCollator) Collator.getInstance()).getRules().replace("<'\u005f'", "<' '<'\u005f'")); + } catch (ParseException e) { + return Collator.getInstance(); + } + } + private FieldType determineFieldType() { if(BibEntry.TYPE_HEADER.equals(this.field[0])) { return FieldType.TYPE; @@ -103,10 +107,6 @@ private FieldType determineFieldType() { } } - public FieldComparator(SaveOrderConfig.SortCriterion sortCriterion) { - this(sortCriterion.field, sortCriterion.descending); - } - @Override public int compare(BibEntry e1, BibEntry e2) { String f1; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java index 8c6c8edee187..f604eca8c865 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java @@ -23,16 +23,21 @@ import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; public class CleanupWorker { private final BibDatabaseContext databaseContext; private final JournalAbbreviationLoader repositoryLoader; + private final JabRefPreferences prefs; private int unsuccessfulRenames; - public CleanupWorker(BibDatabaseContext databaseContext, JournalAbbreviationLoader repositoryLoader) { + + public CleanupWorker(BibDatabaseContext databaseContext, JournalAbbreviationLoader repositoryLoader, + JabRefPreferences prefs) { this.databaseContext = databaseContext; this.repositoryLoader = repositoryLoader; + this.prefs = prefs; } public int getUnsuccessfulRenames() { @@ -73,7 +78,7 @@ private List determineCleanupActions(CleanupPreset preset) { } if (preset.isRenamePDF()) { RenamePdfCleanup cleaner = new RenamePdfCleanup(preset.isRenamePdfOnlyRelativePaths(), databaseContext, - repositoryLoader); + repositoryLoader, prefs); jobs.add(cleaner); unsuccessfulRenames += cleaner.getUnsuccessfulRenames(); } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java index 534824abb78d..db2ebed40805 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java @@ -27,20 +27,23 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.ParsedFileField; +import net.sf.jabref.preferences.JabRefPreferences; public class RenamePdfCleanup implements CleanupJob { private final BibDatabaseContext databaseContext; private final boolean onlyRelativePaths; private final JournalAbbreviationLoader repositoryLoader; + private final JabRefPreferences prefs; private int unsuccessfulRenames; public RenamePdfCleanup(boolean onlyRelativePaths, BibDatabaseContext databaseContext, - JournalAbbreviationLoader repositoryLoader) { + JournalAbbreviationLoader repositoryLoader, JabRefPreferences prefs) { this.databaseContext = Objects.requireNonNull(databaseContext); this.onlyRelativePaths = onlyRelativePaths; this.repositoryLoader = Objects.requireNonNull(repositoryLoader); + this.prefs = Objects.requireNonNull(prefs); } @Override @@ -59,7 +62,7 @@ public List cleanup(BibEntry entry) { } StringBuilder newFilename = new StringBuilder( - FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), entry, repositoryLoader)); + FileUtil.createFileNameFromPattern(databaseContext.getDatabase(), entry, repositoryLoader, prefs)); //Add extension to newFilename newFilename.append('.').append(FileUtil.getFileExtension(realOldFilename).orElse("pdf")); diff --git a/src/main/java/net/sf/jabref/logic/exporter/BibDatabaseWriter.java b/src/main/java/net/sf/jabref/logic/exporter/BibDatabaseWriter.java index f8d74d2f6067..0561174839b6 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/BibDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/logic/exporter/BibDatabaseWriter.java @@ -34,6 +34,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.MetaData; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.bibtex.comparator.BibtexStringComparator; import net.sf.jabref.logic.bibtex.comparator.CrossRefEntryComparator; import net.sf.jabref.logic.bibtex.comparator.FieldComparator; @@ -178,7 +179,8 @@ public E savePartOfDatabase(BibDatabaseContext bibDatabaseContext, writePreamble(bibDatabaseContext.getDatabase().getPreamble()); // Write strings if there are any. - writeStrings(bibDatabaseContext.getDatabase(), preferences.isReformatFile()); + writeStrings(bibDatabaseContext.getDatabase(), preferences.isReformatFile(), + preferences.getLatexFieldFormatterPreferences()); // Write database entries. List sortedEntries = getSortedEntries(bibDatabaseContext, entries, preferences); @@ -196,7 +198,8 @@ public E savePartOfDatabase(BibDatabaseContext bibDatabaseContext, entryType -> typesToWrite.put(entryType.getName(), entryType)); } - writeEntry(entry, bibDatabaseContext.getMode(), preferences.isReformatFile()); + writeEntry(entry, bibDatabaseContext.getMode(), preferences.isReformatFile(), + preferences.getLatexFieldFormatterPreferences()); } if (preferences.getSaveType() != SavePreferences.DatabaseSaveType.PLAIN_BIBTEX) { @@ -220,7 +223,8 @@ public E savePartOfDatabase(BibDatabaseContext bibDatabaseContext, protected abstract void writePrelogue(BibDatabaseContext bibDatabaseContext, Charset encoding) throws SaveException; - protected abstract void writeEntry(BibEntry entry, BibDatabaseMode mode, Boolean isReformatFile) throws SaveException; + protected abstract void writeEntry(BibEntry entry, BibDatabaseMode mode, Boolean isReformatFile, + LatexFieldFormatterPreferences latexFieldFormatterPreferences) throws SaveException; protected abstract void writeEpilogue(String epilogue) throws SaveException; @@ -247,7 +251,8 @@ protected void writeMetaData(MetaData metaData) throws SaveException { * * @param database The database whose strings we should write. */ - private void writeStrings(BibDatabase database, Boolean reformatFile) throws SaveException { + private void writeStrings(BibDatabase database, Boolean reformatFile, + LatexFieldFormatterPreferences latexFieldFormatterPreferences) throws SaveException { List strings = database.getStringKeySet().stream().map(database::getString).collect( Collectors.toList()); strings.sort(new BibtexStringComparator(true)); @@ -263,7 +268,8 @@ private void writeStrings(BibDatabase database, Boolean reformatFile) throws Sav boolean isFirstStringInType = true; for (BibtexString bs : strings) { if (remaining.containsKey(bs.getName()) && (bs.getType() == t)) { - writeString(bs, isFirstStringInType, remaining, maxKeyLength, reformatFile); + writeString(bs, isFirstStringInType, remaining, maxKeyLength, reformatFile, + latexFieldFormatterPreferences); isFirstStringInType = false; } } @@ -271,7 +277,7 @@ private void writeStrings(BibDatabase database, Boolean reformatFile) throws Sav } protected void writeString(BibtexString bibtexString, boolean isFirstString, Map remaining, int maxKeyLength, - Boolean reformatFile) + Boolean reformatFile, LatexFieldFormatterPreferences latexFieldFormatterPreferences) throws SaveException { // First remove this from the "remaining" list so it can't cause problem with circular refs: remaining.remove(bibtexString.getName()); @@ -290,14 +296,16 @@ protected void writeString(BibtexString bibtexString, boolean isFirstString, Map // If the label we found exists as a key in the "remaining" Map, we go on and write it now: if (remaining.containsKey(label)) { BibtexString referred = remaining.get(label); - writeString(referred, isFirstString, remaining, maxKeyLength, reformatFile); + writeString(referred, isFirstString, remaining, maxKeyLength, reformatFile, + latexFieldFormatterPreferences); } } - writeString(bibtexString, isFirstString, maxKeyLength, reformatFile); + writeString(bibtexString, isFirstString, maxKeyLength, reformatFile, latexFieldFormatterPreferences); } - protected abstract void writeString(BibtexString bibtexString, boolean isFirstString, int maxKeyLength, Boolean reformatFile) + protected abstract void writeString(BibtexString bibtexString, boolean isFirstString, int maxKeyLength, + Boolean reformatFile, LatexFieldFormatterPreferences latexFieldFormatterPreferences) throws SaveException; protected void writeEntryTypeDefinitions(Map types) throws SaveException { diff --git a/src/main/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriter.java b/src/main/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriter.java index 1141323cf3b8..173a0c8ae9dc 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriter.java +++ b/src/main/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriter.java @@ -25,6 +25,7 @@ import net.sf.jabref.MetaData; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; @@ -37,6 +38,7 @@ public class BibtexDatabaseWriter extends BibDatabaseWrit private static final String COMMENT_PREFIX = "@Comment"; private static final String PREAMBLE_PREFIX = "@Preamble"; + public BibtexDatabaseWriter(SaveSessionFactory saveSessionFactory) { super(saveSessionFactory); } @@ -85,7 +87,8 @@ protected void writePreamble(String preamble) throws SaveException { } @Override - protected void writeString(BibtexString bibtexString, boolean isFirstString, int maxKeyLength, Boolean reformatFile) throws SaveException { + protected void writeString(BibtexString bibtexString, boolean isFirstString, int maxKeyLength, Boolean reformatFile, + LatexFieldFormatterPreferences latexFieldFormatterPreferences) throws SaveException { try { // If the string has not been modified, write it back as it was if (!reformatFile && !bibtexString.hasChanged()) { @@ -109,7 +112,9 @@ protected void writeString(BibtexString bibtexString, boolean isFirstString, int getWriter().write("{}"); } else { try { - String formatted = new LatexFieldFormatter().format(bibtexString.getContent(), LatexFieldFormatter.BIBTEX_STRING); + String formatted = new LatexFieldFormatter(latexFieldFormatterPreferences) + .format(bibtexString.getContent(), + LatexFieldFormatter.BIBTEX_STRING); getWriter().write(formatted); } catch (IllegalArgumentException ex) { throw new IllegalArgumentException( @@ -153,8 +158,10 @@ protected void writePrelogue(BibDatabaseContext bibDatabaseContext, Charset enco } @Override - protected void writeEntry(BibEntry entry, BibDatabaseMode mode, Boolean isReformatFile) throws SaveException { - BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new LatexFieldFormatter(), true); + protected void writeEntry(BibEntry entry, BibDatabaseMode mode, Boolean isReformatFile, + LatexFieldFormatterPreferences latexFieldFormatterPreferences) throws SaveException { + BibEntryWriter bibtexEntryWriter = new BibEntryWriter( + new LatexFieldFormatter(latexFieldFormatterPreferences), true); try { bibtexEntryWriter.write(entry, getWriter(), mode, isReformatFile); } catch (IOException e) { diff --git a/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java b/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java index 7b3ab7786a7a..855c41fad374 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java +++ b/src/main/java/net/sf/jabref/logic/exporter/CustomExportList.java @@ -21,7 +21,6 @@ import java.util.Optional; import java.util.TreeMap; -import net.sf.jabref.Globals; import net.sf.jabref.preferences.JabRefPreferences; import ca.odell.glazedlists.BasicEventList; @@ -52,9 +51,9 @@ public CustomExportList(Comparator> comp) { sorted = new SortedList<>(list, comp); } - public Map getCustomExportFormats() { + public Map getCustomExportFormats(JabRefPreferences prefs) { formats.clear(); - readPrefs(); + readPrefs(prefs); return formats; } @@ -66,18 +65,18 @@ public EventList> getSortedList() { return sorted; } - private void readPrefs() { + private void readPrefs(JabRefPreferences prefs) { formats.clear(); list.clear(); int i = 0; List s; - while (!((s = Globals.prefs.getStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i)).isEmpty())) { + while (!((s = prefs.getStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i)).isEmpty())) { Optional format = createFormat(s); if (format.isPresent()) { formats.put(format.get().getConsoleName(), format.get()); list.add(s); } else { - String customExportFormat = Globals.prefs.get(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i); + String customExportFormat = prefs.get(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i); LOGGER.error("Error initializing custom export format from string " + customExportFormat); } i++; @@ -113,22 +112,22 @@ public void remove(List toRemove) { }); } - public void store() { + public void store(JabRefPreferences prefs) { if (list.isEmpty()) { - purge(0); + purge(0, prefs); } else { for (int i = 0; i < list.size(); i++) { - Globals.prefs.putStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i, list.get(i)); + prefs.putStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i, list.get(i)); } - purge(list.size()); + purge(list.size(), prefs); } } - private void purge(int from) { + private void purge(int from, JabRefPreferences prefs) { int i = from; - while (!Globals.prefs.getStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i).isEmpty()) { - Globals.prefs.remove(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i); + while (!prefs.getStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i).isEmpty()) { + prefs.remove(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i); i++; } } diff --git a/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java b/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java index 4cb6ba4a357d..9e44a4337c5e 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java +++ b/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java @@ -219,7 +219,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String // Print header try (Reader reader = getReader(lfFileName + ".begin.layout")) { - LayoutHelper layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); + LayoutHelper layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); beginLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was cast, export filter doesn't have a begin @@ -245,7 +245,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String Layout defLayout; LayoutHelper layoutHelper; try (Reader reader = getReader(lfFileName + ".layout")) { - layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); + layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); defLayout = layoutHelper.getLayoutFromText(); } if (defLayout != null) { @@ -267,7 +267,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String } else { try (Reader reader = getReader(lfFileName + '.' + type + ".layout")) { // We try to get a type-specific layout for this entry. - layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); + layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); layout = layoutHelper.getLayoutFromText(); layouts.put(type, layout); if (layout != null) { @@ -291,7 +291,7 @@ public void performExport(final BibDatabaseContext databaseContext, final String // changed section - begin (arudert) Layout endLayout = null; try (Reader reader = getReader(lfFileName + ".end.layout")) { - layoutHelper = new LayoutHelper(reader, Globals.journalAbbreviationLoader); + layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); endLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was thrown, export filter doesn't have an end diff --git a/src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java b/src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java index f5b1de8a3eaa..94f2a582fa3f 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java +++ b/src/main/java/net/sf/jabref/logic/exporter/ExportFormats.java @@ -20,7 +20,6 @@ import java.util.Map; import java.util.TreeMap; -import net.sf.jabref.Globals; import net.sf.jabref.logic.l10n.Localization; public class ExportFormats { @@ -31,7 +30,7 @@ public class ExportFormats { public static int entryNumber; - public static void initAllExports() { + public static void initAllExports(Map customFormats) { ExportFormats.EXPORT_FORMATS.clear(); @@ -66,7 +65,6 @@ public static void initAllExports() { ExportFormats.putFormat(new ModsExportFormat()); // Now add custom export formats - Map customFormats = Globals.prefs.customExports.getCustomExportFormats(); for (IExportFormat format : customFormats.values()) { ExportFormats.putFormat(format); } diff --git a/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java b/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java index d482609035a3..06fb60914292 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java +++ b/src/main/java/net/sf/jabref/logic/exporter/SavePreferences.java @@ -2,7 +2,7 @@ import java.nio.charset.Charset; -import net.sf.jabref.Globals; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.config.SaveOrderConfig; import net.sf.jabref.preferences.JabRefPreferences; @@ -15,13 +15,15 @@ public class SavePreferences { private final boolean makeBackup; private final DatabaseSaveType saveType; private final boolean takeMetadataSaveOrderInAccount; + private final LatexFieldFormatterPreferences latexFieldFormatterPreferences; public SavePreferences() { - this(true, null, null, false, DatabaseSaveType.ALL, true, false); + this(true, null, null, false, DatabaseSaveType.ALL, true, false, new LatexFieldFormatterPreferences()); } public SavePreferences(Boolean saveInOriginalOrder, SaveOrderConfig saveOrder, Charset encoding, Boolean makeBackup, - DatabaseSaveType saveType, Boolean takeMetadataSaveOrderInAccount, Boolean reformatFile) { + DatabaseSaveType saveType, Boolean takeMetadataSaveOrderInAccount, Boolean reformatFile, + LatexFieldFormatterPreferences latexFieldFormatterPreferences) { this.saveInOriginalOrder = saveInOriginalOrder; this.saveOrder = saveOrder; this.encoding = encoding; @@ -29,13 +31,14 @@ public SavePreferences(Boolean saveInOriginalOrder, SaveOrderConfig saveOrder, C this.saveType = saveType; this.takeMetadataSaveOrderInAccount = takeMetadataSaveOrderInAccount; this.reformatFile = reformatFile; + this.latexFieldFormatterPreferences = latexFieldFormatterPreferences; } public static SavePreferences loadForExportFromPreferences(JabRefPreferences preferences) { - Boolean saveInOriginalOrder = Globals.prefs.getBoolean(JabRefPreferences.EXPORT_IN_ORIGINAL_ORDER); + Boolean saveInOriginalOrder = preferences.getBoolean(JabRefPreferences.EXPORT_IN_ORIGINAL_ORDER); SaveOrderConfig saveOrder = null; if (!saveInOriginalOrder) { - if (Globals.prefs.getBoolean(JabRefPreferences.EXPORT_IN_SPECIFIED_ORDER)) { + if (preferences.getBoolean(JabRefPreferences.EXPORT_IN_SPECIFIED_ORDER)) { saveOrder = SaveOrderConfig.loadExportSaveOrderFromPreferences(preferences); } else { saveOrder = SaveOrderConfig.loadTableSaveOrderFromPreferences(preferences); @@ -46,8 +49,10 @@ public static SavePreferences loadForExportFromPreferences(JabRefPreferences pre DatabaseSaveType saveType = DatabaseSaveType.ALL; Boolean takeMetadataSaveOrderInAccount = false; Boolean reformatFile = preferences.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT); + LatexFieldFormatterPreferences latexFieldFormatterPreferences = LatexFieldFormatterPreferences + .fromPreferences(preferences); return new SavePreferences(saveInOriginalOrder, saveOrder, encoding, makeBackup, saveType, - takeMetadataSaveOrderInAccount, reformatFile); + takeMetadataSaveOrderInAccount, reformatFile, latexFieldFormatterPreferences); } public static SavePreferences loadForSaveFromPreferences(JabRefPreferences preferences) { @@ -58,8 +63,10 @@ public static SavePreferences loadForSaveFromPreferences(JabRefPreferences prefe DatabaseSaveType saveType = DatabaseSaveType.ALL; Boolean takeMetadataSaveOrderInAccount = true; Boolean reformatFile = preferences.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT); + LatexFieldFormatterPreferences latexFieldFormatterPreferences = LatexFieldFormatterPreferences + .fromPreferences(preferences); return new SavePreferences(saveInOriginalOrder, saveOrder, encoding, makeBackup, saveType, - takeMetadataSaveOrderInAccount, reformatFile); + takeMetadataSaveOrderInAccount, reformatFile, latexFieldFormatterPreferences); } public Boolean getTakeMetadataSaveOrderInAccount() { @@ -76,7 +83,7 @@ public boolean isSaveInOriginalOrder() { public SavePreferences withSaveInOriginalOrder(Boolean saveInOriginalOrder) { return new SavePreferences(saveInOriginalOrder, this.saveOrder, this.encoding, this.makeBackup, this.saveType, - this.takeMetadataSaveOrderInAccount, this.reformatFile); + this.takeMetadataSaveOrderInAccount, this.reformatFile, this.latexFieldFormatterPreferences); } public boolean getMakeBackup() { @@ -85,7 +92,7 @@ public boolean getMakeBackup() { public SavePreferences withMakeBackup(Boolean makeBackup) { return new SavePreferences(this.saveInOriginalOrder, this.saveOrder, this.encoding, makeBackup, this.saveType, - this.takeMetadataSaveOrderInAccount, this.reformatFile); + this.takeMetadataSaveOrderInAccount, this.reformatFile, this.latexFieldFormatterPreferences); } public Charset getEncoding() { @@ -94,7 +101,7 @@ public Charset getEncoding() { public SavePreferences withEncoding(Charset encoding) { return new SavePreferences(this.saveInOriginalOrder, this.saveOrder, encoding, this.makeBackup, this.saveType, - this.takeMetadataSaveOrderInAccount, this.reformatFile); + this.takeMetadataSaveOrderInAccount, this.reformatFile, this.latexFieldFormatterPreferences); } public DatabaseSaveType getSaveType() { @@ -103,7 +110,7 @@ public DatabaseSaveType getSaveType() { public SavePreferences withSaveType(DatabaseSaveType saveType) { return new SavePreferences(this.saveInOriginalOrder, this.saveOrder, this.encoding, this.makeBackup, saveType, - this.takeMetadataSaveOrderInAccount, this.reformatFile); + this.takeMetadataSaveOrderInAccount, this.reformatFile, this.latexFieldFormatterPreferences); } public Boolean isReformatFile() { @@ -112,13 +119,17 @@ public Boolean isReformatFile() { public SavePreferences withReformatFile(boolean reformatFile) { return new SavePreferences(this.saveInOriginalOrder, this.saveOrder, this.encoding, this.makeBackup, - this.saveType, this.takeMetadataSaveOrderInAccount, reformatFile); + this.saveType, this.takeMetadataSaveOrderInAccount, reformatFile, this.latexFieldFormatterPreferences); } public Charset getEncodingOrDefault() { return encoding == null ? Charset.defaultCharset() : encoding; } + public LatexFieldFormatterPreferences getLatexFieldFormatterPreferences() { + return latexFieldFormatterPreferences; + } + public enum DatabaseSaveType { ALL, PLAIN_BIBTEX diff --git a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java index 875c4745de9f..db5b8ac43658 100644 --- a/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java +++ b/src/main/java/net/sf/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java @@ -20,12 +20,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.Globals; import net.sf.jabref.logic.formatter.Formatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.logic.util.strings.HTMLUnicodeConversionMaps; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -41,7 +39,6 @@ public class HtmlToLatexFormatter implements LayoutFormatter, Formatter { private static final Pattern ESCAPED_PATTERN3 = Pattern.compile("&#([x]*)([0]*)(\\p{XDigit}+);"); private static final Pattern ESCAPED_PATTERN4 = Pattern.compile("&(\\w+);"); - @Override public String format(String text) { String result = Objects.requireNonNull(text); @@ -52,15 +49,8 @@ public String format(String text) { StringBuilder sb = new StringBuilder(); // Deal with the form kand k - // If the result is in text or equation form can be controlled - // From the "Advanced settings" tab - if (Globals.prefs.getBoolean(JabRefPreferences.USE_CONVERT_TO_EQUATION)) { - result = result.replaceAll("<[ ]?sup>([^<]+)", "\\$\\^\\{$1\\}\\$"); - result = result.replaceAll("<[ ]?sub>([^<]+)", "\\$_\\{$1\\}\\$"); - } else { - result = result.replaceAll("<[ ]?sup>([^<]+)", "\\\\textsuperscript\\{$1\\}"); - result = result.replaceAll("<[ ]?sub>([^<]+)", "\\\\textsubscript\\{$1\\}"); - } + result = result.replaceAll("<[ ]?sup>([^<]+)", "\\\\textsuperscript\\{$1\\}"); + result = result.replaceAll("<[ ]?sub>([^<]+)", "\\\\textsubscript\\{$1\\}"); // TODO: maybe rewrite this based on regular expressions instead // Note that (at least) the IEEE Xplore fetcher must be fixed as it relies on the current way to diff --git a/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java b/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java index 10f1ea3c35d3..dd2812a434e1 100644 --- a/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/AbstractGroup.java @@ -23,6 +23,7 @@ import net.sf.jabref.logic.search.SearchMatcher; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; /** * A group of BibtexEntries. @@ -62,9 +63,9 @@ public abstract class AbstractGroup implements SearchMatcher { * @throws ParseException If an error occurred and a group could not be created, * e.g. due to a malformed regular expression. */ - public static AbstractGroup fromString(String s) throws ParseException { + public static AbstractGroup fromString(String s, JabRefPreferences jabRefPreferences) throws ParseException { if (s.startsWith(KeywordGroup.ID)) { - return KeywordGroup.fromString(s); + return KeywordGroup.fromString(s, jabRefPreferences); } if (s.startsWith(AllEntriesGroup.ID)) { return AllEntriesGroup.fromString(s); @@ -73,7 +74,7 @@ public static AbstractGroup fromString(String s) throws ParseException { return SearchGroup.fromString(s); } if (s.startsWith(ExplicitGroup.ID)) { - return ExplicitGroup.fromString(s); + return ExplicitGroup.fromString(s, jabRefPreferences); } return null; // unknown group } @@ -208,7 +209,7 @@ public void setHierarchicalContext(GroupHierarchyType context) { /** * Returns a short description of the group in HTML (for a tooltip). */ - public abstract String getShortDescription(); + public abstract String getShortDescription(boolean showDynamic); // by general AbstractGroup contract, toString() must return // something from which this object can be reconstructed diff --git a/src/main/java/net/sf/jabref/logic/groups/AllEntriesGroup.java b/src/main/java/net/sf/jabref/logic/groups/AllEntriesGroup.java index f4b72ab3b72e..c4e45ab03aa7 100644 --- a/src/main/java/net/sf/jabref/logic/groups/AllEntriesGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/AllEntriesGroup.java @@ -94,7 +94,7 @@ public String getDescription() { } @Override - public String getShortDescription() { + public String getShortDescription(boolean showDynamic) { return Localization.lang("All Entries (this group cannot be edited or removed)"); } diff --git a/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java b/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java index fc3a801b0764..fb0d9b67010e 100644 --- a/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/ExplicitGroup.java @@ -25,6 +25,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.strings.QuotedStringTokenizer; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,11 +43,12 @@ public class ExplicitGroup extends KeywordGroup { private static final Log LOGGER = LogFactory.getLog(ExplicitGroup.class); - public ExplicitGroup(String name, GroupHierarchyType context) throws ParseException { - super(name, "groups", name, true, false, context); + public ExplicitGroup(String name, GroupHierarchyType context, JabRefPreferences jabRefPreferences) + throws ParseException { + super(name, "groups", name, true, false, context, jabRefPreferences); } - public static ExplicitGroup fromString(String s) throws ParseException { + public static ExplicitGroup fromString(String s, JabRefPreferences jabRefPreferences) throws ParseException { if (!s.startsWith(ExplicitGroup.ID)) { throw new IllegalArgumentException("ExplicitGroup cannot be created from \"" + s + "\"."); } @@ -55,7 +57,7 @@ public static ExplicitGroup fromString(String s) throws ParseException { String name = tok.nextToken(); int context = Integer.parseInt(tok.nextToken()); - ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumber(context)); + ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumber(context), jabRefPreferences); newGroup.addLegacyEntryKeys(tok); return newGroup; } @@ -80,7 +82,7 @@ public void addLegacyEntryKey(String key) { @Override public AbstractGroup deepCopy() { try { - ExplicitGroup copy = new ExplicitGroup(getName(), getContext()); + ExplicitGroup copy = new ExplicitGroup(getName(), getContext(), jabRefPreferences); copy.legacyEntryKeys.addAll(legacyEntryKeys); return copy; } catch (ParseException exception) { @@ -143,7 +145,7 @@ public static String getDescriptionForPreview() { } @Override - public String getShortDescription() { + public String getShortDescription(boolean showDynamic) { StringBuilder sb = new StringBuilder(); sb.append("").append(getName()).append(" -").append(Localization.lang("static group")); switch (getHierarchicalContext()) { diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java index c0cbba8d536b..7ef67103cc5e 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupTreeNode.java @@ -27,6 +27,7 @@ import net.sf.jabref.logic.search.matchers.MatcherSets; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; /** * A node in the groups tree that holds exactly one AbstractGroup. @@ -248,8 +249,9 @@ public GroupTreeNode copyNode() { return GroupTreeNode.fromGroup(group); } - public static GroupTreeNode parse(List orderedData) throws ParseException { - return GroupsParser.importGroups(orderedData); + public static GroupTreeNode parse(List orderedData, JabRefPreferences jabRefPreferences) + throws ParseException { + return GroupsParser.importGroups(orderedData, jabRefPreferences); } /** diff --git a/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java b/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java index 82aae0af35a1..6d73a378a2ac 100644 --- a/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java +++ b/src/main/java/net/sf/jabref/logic/groups/GroupsParser.java @@ -21,13 +21,15 @@ import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.preferences.JabRefPreferences; /** * Converts string representation of groups to a parsed {@link GroupTreeNode}. */ class GroupsParser { - public static GroupTreeNode importGroups(List orderedData) throws ParseException { + public static GroupTreeNode importGroups(List orderedData, JabRefPreferences jabRefPreferences) + throws ParseException { GroupTreeNode cursor = null; GroupTreeNode root = null; for (String string : orderedData) { @@ -42,7 +44,7 @@ public static GroupTreeNode importGroups(List orderedData) throws ParseE throw new ParseException(Localization.lang("Expected \"%0\" to contain whitespace", string)); } int level = Integer.parseInt(string.substring(0, spaceIndex)); - AbstractGroup group = AbstractGroup.fromString(string.substring(spaceIndex + 1)); + AbstractGroup group = AbstractGroup.fromString(string.substring(spaceIndex + 1), jabRefPreferences); GroupTreeNode newNode = GroupTreeNode.fromGroup(group); if (cursor == null) { // create new root diff --git a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java index 257df6c11148..3d1abdf3334d 100644 --- a/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/KeywordGroup.java @@ -22,7 +22,6 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -import net.sf.jabref.Globals; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.strings.QuotedStringTokenizer; @@ -47,7 +46,8 @@ public class KeywordGroup extends AbstractGroup { private final boolean caseSensitive; private final boolean regExp; private Pattern pattern; - private List searchWords; + private final List searchWords; + protected final JabRefPreferences jabRefPreferences; private static final Log LOGGER = LogFactory.getLog(KeywordGroup.class); @@ -57,7 +57,7 @@ public class KeywordGroup extends AbstractGroup { */ public KeywordGroup(String name, String searchField, String searchExpression, boolean caseSensitive, boolean regExp, - GroupHierarchyType context) throws ParseException { + GroupHierarchyType context, JabRefPreferences jabRefPreferences) throws ParseException { super(name, context); this.searchField = searchField; this.searchExpression = searchExpression; @@ -66,6 +66,7 @@ public KeywordGroup(String name, String searchField, if (this.regExp) { compilePattern(); } + this.jabRefPreferences = jabRefPreferences; this.searchWords = EntryUtil.getStringAsWords(searchExpression); } @@ -84,7 +85,7 @@ private void compilePattern() throws ParseException { * @param s The String representation obtained from * KeywordGroup.toString() */ - public static AbstractGroup fromString(String s) throws ParseException { + public static AbstractGroup fromString(String s, JabRefPreferences jabRefPreferences) throws ParseException { if (!s.startsWith(KeywordGroup.ID)) { throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + s + "\"."); } @@ -100,7 +101,7 @@ public static AbstractGroup fromString(String s) throws ParseException { return new KeywordGroup(StringUtil.unquote(name, AbstractGroup.QUOTE_CHAR), StringUtil.unquote(field, AbstractGroup.QUOTE_CHAR), StringUtil.unquote(expression, AbstractGroup.QUOTE_CHAR), caseSensitive, regExp, - GroupHierarchyType.getByNumber(context)); + GroupHierarchyType.getByNumber(context), jabRefPreferences); } /** @@ -140,7 +141,7 @@ public Optional add(List entriesToAdd) { if (!contains(entry)) { String oldContent = entry .getField(searchField); - String pre = Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR); + String pre = jabRefPreferences.get(JabRefPreferences.KEYWORD_SEPARATOR); String newContent = (oldContent == null ? "" : oldContent + pre) + searchExpression; @@ -279,7 +280,7 @@ private void removeMatches(BibEntry entry) { int i; int j; int k; - final String separator = Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR); + final String separator = jabRefPreferences.get(JabRefPreferences.KEYWORD_SEPARATOR); while ((i = haystack.indexOf(needle)) >= 0) { sbOrig.replace(i, i + needle.length(), ""); sbLower.replace(i, i + needle.length(), ""); @@ -308,7 +309,7 @@ private void removeMatches(BibEntry entry) { public AbstractGroup deepCopy() { try { return new KeywordGroup(getName(), searchField, searchExpression, - caseSensitive, regExp, getContext()); + caseSensitive, regExp, getContext(), jabRefPreferences); } catch (ParseException exception) { // this should never happen, because the constructor obviously succeeded in creating _this_ instance! LOGGER.error("Internal error in KeywordGroup.deepCopy(). " @@ -367,10 +368,10 @@ public static String getDescriptionForPreview(String field, String expr, boolean } @Override - public String getShortDescription() { + public String getShortDescription(boolean showDynamic) { StringBuilder sb = new StringBuilder(); sb.append(""); - if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_DYNAMIC)) { + if (showDynamic) { sb.append("").append(StringUtil.quoteForHTML(getName())).append(""); } else { sb.append(StringUtil.quoteForHTML(getName())); diff --git a/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java b/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java index 8c5d30034bc0..e2ded3904739 100644 --- a/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java +++ b/src/main/java/net/sf/jabref/logic/groups/SearchGroup.java @@ -18,13 +18,11 @@ import java.util.List; import java.util.Optional; -import net.sf.jabref.Globals; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.strings.QuotedStringTokenizer; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,11 +40,11 @@ public class SearchGroup extends AbstractGroup { private static final Log LOGGER = LogFactory.getLog(SearchGroup.class); - /** * Creates a SearchGroup with the specified properties. */ - public SearchGroup(String name, String searchExpression, boolean caseSensitive, boolean regExp, GroupHierarchyType context) { + public SearchGroup(String name, String searchExpression, boolean caseSensitive, boolean regExp, + GroupHierarchyType context) { super(name, context); this.query = new SearchQuery(searchExpression, caseSensitive, regExp); @@ -170,10 +168,10 @@ public String getDescription() { } @Override - public String getShortDescription() { + public String getShortDescription(boolean showDynamic) { StringBuilder sb = new StringBuilder(); sb.append(""); - if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_DYNAMIC)) { + if (showDynamic) { sb.append("").append(StringUtil.quoteForHTML(getName())).append(""); } else { sb.append(StringUtil.quoteForHTML(getName())); diff --git a/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java index a42cd306422c..0926e967f2d5 100644 --- a/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java +++ b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationLoader.java @@ -22,9 +22,6 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.Globals; -import net.sf.jabref.preferences.JabRefPreferences; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -38,7 +35,8 @@ public class JournalAbbreviationLoader { private static final String JOURNALS_IEEE_ABBREVIATION_LIST_WITH_TEXT = "/journals/IEEEJournalListText.txt"; private JournalAbbreviationRepository journalAbbrev; - public void update(JabRefPreferences jabRefPreferences) { + + public void update(JournalAbbreviationPreferences journalAbbreviationPreferences) { journalAbbrev = new JournalAbbreviationRepository(); // the order of reading the journal lists is important @@ -49,14 +47,14 @@ public void update(JabRefPreferences jabRefPreferences) { journalAbbrev.addEntries(readJournalListFromResource(JOURNALS_FILE_BUILTIN)); // read IEEE list - if (jabRefPreferences.getBoolean(JabRefPreferences.USE_IEEE_ABRV)) { + if (journalAbbreviationPreferences.isUseIEEEAbbreviations()) { journalAbbrev.addEntries(getOfficialIEEEAbbreviations()); } else { journalAbbrev.addEntries(getStandardIEEEAbbreviations()); } // Read external lists - List lists = jabRefPreferences.getStringList(JabRefPreferences.EXTERNAL_JOURNAL_LISTS); + List lists = journalAbbreviationPreferences.getExternalJournalLists(); if (!(lists.isEmpty())) { Collections.reverse(lists); for (String filename : lists) { @@ -70,11 +68,12 @@ public void update(JabRefPreferences jabRefPreferences) { } // Read personal list - String personalJournalList = jabRefPreferences.get(JabRefPreferences.PERSONAL_JOURNAL_LIST); + String personalJournalList = journalAbbreviationPreferences.getPersonalJournalLists(); if ((personalJournalList != null) && !personalJournalList.trim().isEmpty()) { try { journalAbbrev.addEntries( - readJournalListFromFile(new File(personalJournalList), Globals.prefs.getDefaultEncoding())); + readJournalListFromFile(new File(personalJournalList), + journalAbbreviationPreferences.getDefaultEncoding())); } catch (FileNotFoundException e) { LOGGER.info("Personal journal list file '" + personalJournalList + "' not found.", e); } @@ -94,9 +93,9 @@ public static List getBuiltInAbbreviations() { return readJournalListFromResource(JOURNALS_FILE_BUILTIN); } - public JournalAbbreviationRepository getRepository() { + public JournalAbbreviationRepository getRepository(JournalAbbreviationPreferences journalAbbreviationPreferences) { if (journalAbbrev == null) { - update(Globals.prefs); + update(journalAbbreviationPreferences); } return journalAbbrev; } diff --git a/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationPreferences.java b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationPreferences.java new file mode 100644 index 000000000000..3ba35a8b3b21 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/journals/JournalAbbreviationPreferences.java @@ -0,0 +1,46 @@ +package net.sf.jabref.logic.journals; + +import java.nio.charset.Charset; +import java.util.List; + +import net.sf.jabref.preferences.JabRefPreferences; + +public class JournalAbbreviationPreferences { + + private final List externalJournalLists; + private final String personalJournalLists; + private final boolean useIEEEAbbreviations; + private final Charset defaultEncoding; + + + public JournalAbbreviationPreferences(List externalJournalLists, String personalJournalLists, + boolean useIEEEAbbreviations, Charset defaultEncoding) { + this.externalJournalLists = externalJournalLists; + this.personalJournalLists = personalJournalLists; + this.useIEEEAbbreviations = useIEEEAbbreviations; + this.defaultEncoding = defaultEncoding; + } + + public static JournalAbbreviationPreferences fromPreferences(JabRefPreferences jabRefPreferences) { + return new JournalAbbreviationPreferences( + jabRefPreferences.getStringList(JabRefPreferences.EXTERNAL_JOURNAL_LISTS), + jabRefPreferences.get(JabRefPreferences.PERSONAL_JOURNAL_LIST), + jabRefPreferences.getBoolean(JabRefPreferences.USE_IEEE_ABRV), jabRefPreferences.getDefaultEncoding()); + } + + public List getExternalJournalLists() { + return externalJournalLists; + } + + public String getPersonalJournalLists() { + return personalJournalLists; + } + + public boolean isUseIEEEAbbreviations() { + return useIEEEAbbreviations; + } + + public Charset getDefaultEncoding() { + return defaultEncoding; + } +} diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/DatabaseLabelPattern.java b/src/main/java/net/sf/jabref/logic/labelpattern/DatabaseLabelPattern.java index 2e10becff78d..4c3836e9e496 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/DatabaseLabelPattern.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/DatabaseLabelPattern.java @@ -17,13 +17,20 @@ import java.util.List; -import net.sf.jabref.Globals; +import net.sf.jabref.preferences.JabRefPreferences; public class DatabaseLabelPattern extends AbstractLabelPattern { + private final JabRefPreferences prefs; + + + public DatabaseLabelPattern(JabRefPreferences prefs) { + this.prefs = prefs; + } + @Override public List getLastLevelLabelPattern(String key) { - return Globals.prefs.getKeyPattern().getValue(key); + return prefs.getKeyPattern().getValue(key); } } diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index 555bb8c6f6a9..c36447041889 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -26,7 +26,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.Globals; import net.sf.jabref.MetaData; import net.sf.jabref.logic.formatter.casechanger.Word; import net.sf.jabref.logic.layout.format.RemoveLatexCommands; @@ -427,7 +426,7 @@ public static List split(String labelPattern) { * @param entry a BibEntry * @return modified BibEntry */ - public static void makeLabel(MetaData metaData, BibDatabase dBase, BibEntry entry) { + public static void makeLabel(MetaData metaData, BibDatabase dBase, BibEntry entry, JabRefPreferences prefs) { database = dBase; String key; StringBuilder stringBuilder = new StringBuilder(); @@ -474,9 +473,9 @@ public static void makeLabel(MetaData metaData, BibDatabase dBase, BibEntry entr key = checkLegalKey(stringBuilder.toString()); // Remove Regular Expressions while generating Keys - String regex = Globals.prefs.get(JabRefPreferences.KEY_PATTERN_REGEX); + String regex = prefs.get(JabRefPreferences.KEY_PATTERN_REGEX); if ((regex != null) && !regex.trim().isEmpty()) { - String replacement = Globals.prefs.get(JabRefPreferences.KEY_PATTERN_REPLACEMENT); + String replacement = prefs.get(JabRefPreferences.KEY_PATTERN_REPLACEMENT); key = key.replaceAll(regex, replacement); } @@ -494,8 +493,8 @@ public static void makeLabel(MetaData metaData, BibDatabase dBase, BibEntry entr occurrences--; // No change, so we can accept one dupe. } - boolean alwaysAddLetter = Globals.prefs.getBoolean(JabRefPreferences.KEY_GEN_ALWAYS_ADD_LETTER); - boolean firstLetterA = Globals.prefs.getBoolean(JabRefPreferences.KEY_GEN_FIRST_LETTER_A); + boolean alwaysAddLetter = prefs.getBoolean(JabRefPreferences.KEY_GEN_ALWAYS_ADD_LETTER); + boolean firstLetterA = prefs.getBoolean(JabRefPreferences.KEY_GEN_FIRST_LETTER_A); if (!alwaysAddLetter && (occurrences == 0)) { // No dupes found, so we can just go ahead. diff --git a/src/main/java/net/sf/jabref/logic/layout/Layout.java b/src/main/java/net/sf/jabref/logic/layout/Layout.java index 7a497a5e043e..7093d8a311a3 100644 --- a/src/main/java/net/sf/jabref/logic/layout/Layout.java +++ b/src/main/java/net/sf/jabref/logic/layout/Layout.java @@ -25,6 +25,7 @@ import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -41,7 +42,7 @@ public class Layout { private static final Log LOGGER = LogFactory.getLog(Layout.class); - public Layout(List parsedEntries, JournalAbbreviationLoader repositoryLoader) { + public Layout(List parsedEntries, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) { List tmpEntries = new ArrayList<>(parsedEntries.size()); List blockEntries = null; @@ -67,7 +68,7 @@ public Layout(List parsedEntries, JournalAbbreviationLoader repositor blockEntries.add(parsedEntry); le = new LayoutEntry(blockEntries, parsedEntry.i == LayoutHelper.IS_FIELD_END ? LayoutHelper.IS_FIELD_START : LayoutHelper.IS_GROUP_START, - repositoryLoader); + prefs, repositoryLoader); tmpEntries.add(le); blockEntries = null; } else { @@ -82,7 +83,7 @@ public Layout(List parsedEntries, JournalAbbreviationLoader repositor } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, repositoryLoader)); + tmpEntries.add(new LayoutEntry(parsedEntry, prefs, repositoryLoader)); } else { blockEntries.add(parsedEntry); } diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java index e16b1d99f868..b434b69a7da3 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java @@ -26,10 +26,10 @@ import java.util.regex.Pattern; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.Globals; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.layout.format.AuthorAbbreviator; import net.sf.jabref.logic.layout.format.AuthorAndsCommaReplacer; import net.sf.jabref.logic.layout.format.AuthorAndsReplacer; @@ -95,6 +95,7 @@ import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -118,8 +119,12 @@ class LayoutEntry { private final JournalAbbreviationLoader repositoryLoader; - public LayoutEntry(StringInt si, JournalAbbreviationLoader repositoryLoader) { + private final JabRefPreferences prefs; + + + public LayoutEntry(StringInt si, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) { this.repositoryLoader = repositoryLoader; + this.prefs = prefs; type = si.i; switch (type) { case LayoutHelper.IS_LAYOUT_TEXT: @@ -138,8 +143,10 @@ public LayoutEntry(StringInt si, JournalAbbreviationLoader repositoryLoader) { } } - public LayoutEntry(List parsedEntries, int layoutType, JournalAbbreviationLoader repositoryLoader) { + public LayoutEntry(List parsedEntries, int layoutType, JabRefPreferences prefs, + JournalAbbreviationLoader repositoryLoader) { this.repositoryLoader = repositoryLoader; + this.prefs = prefs; List tmpEntries = new ArrayList<>(); String blockStart = parsedEntries.get(0).s; String blockEnd = parsedEntries.get(parsedEntries.size() - 1).s; @@ -164,7 +171,7 @@ public LayoutEntry(List parsedEntries, int layoutType, JournalAbbrevi blockEntries.add(parsedEntry); int groupType = parsedEntry.i == LayoutHelper.IS_GROUP_END ? LayoutHelper.IS_GROUP_START : LayoutHelper.IS_FIELD_START; - LayoutEntry le = new LayoutEntry(blockEntries, groupType, repositoryLoader); + LayoutEntry le = new LayoutEntry(blockEntries, groupType, prefs, repositoryLoader); tmpEntries.add(le); blockEntries = null; } else { @@ -180,7 +187,7 @@ public LayoutEntry(List parsedEntries, int layoutType, JournalAbbrevi } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, repositoryLoader)); + tmpEntries.add(new LayoutEntry(parsedEntry, prefs, repositoryLoader)); } else { blockEntries.add(parsedEntry); } @@ -507,7 +514,7 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { case "Iso690NamesAuthors": return new Iso690NamesAuthors(); case "JournalAbbreviator": - return new JournalAbbreviator(repositoryLoader); + return new JournalAbbreviator(repositoryLoader, JournalAbbreviationPreferences.fromPreferences(prefs)); case "LastPage": return new LastPage(); case "FormatChars": // For backward compatibility @@ -544,7 +551,7 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { case "Default": return new Default(); case "FileLink": - return new FileLink(); + return new FileLink(prefs); case "Number": return new Number(); case "RisAuthors": @@ -558,7 +565,7 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { case "WrapContent": return new WrapContent(); case "WrapFileLinks": - return new WrapFileLinks(); + return new WrapFileLinks(prefs); default: return new NotFoundFormatter(name); } @@ -575,15 +582,15 @@ private List getOptionalLayout(String formatterName) { List results = new ArrayList<>(formatterStrings.size()); - Map userNameFormatter = NameFormatter.getNameFormatters(); + Map userNameFormatter = NameFormatter.getNameFormatters(prefs); for (List strings : formatterStrings) { String className = strings.get(0).trim(); // Check if this is a name formatter defined by this export filter: - if (Globals.prefs.customExportNameFormatters != null) { - String contents = Globals.prefs.customExportNameFormatters.get(className); + if (prefs.customExportNameFormatters != null) { + String contents = prefs.customExportNameFormatters.get(className); if (contents != null) { NameFormatter nf = new NameFormatter(); nf.setParameter(contents); diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java b/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java index 59785ea4f641..3dfe088d6a35 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java @@ -23,6 +23,7 @@ import java.util.Objects; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.preferences.JabRefPreferences; /** * Helper class to get a Layout object. @@ -51,12 +52,14 @@ public class LayoutHelper { private final PushbackReader in; private final List parsedEntries = new ArrayList<>(); private final JournalAbbreviationLoader repositoryLoader; + private final JabRefPreferences prefs; private boolean endOfFile; - public LayoutHelper(Reader in, JournalAbbreviationLoader repositoryLoader) { + public LayoutHelper(Reader in, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) { this.in = new PushbackReader(Objects.requireNonNull(in)); this.repositoryLoader = Objects.requireNonNull(repositoryLoader); + this.prefs = Objects.requireNonNull(prefs); } public Layout getLayoutFromText() throws IOException { @@ -70,7 +73,7 @@ public Layout getLayoutFromText() throws IOException { } } - return new Layout(parsedEntries, repositoryLoader); + return new Layout(parsedEntries, prefs, repositoryLoader); } public static String getCurrentGroup() { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java index 9108a85e0090..dc9b55a108cb 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java @@ -26,6 +26,7 @@ import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -39,8 +40,13 @@ public class FileLink implements ParamLayoutFormatter { private static final Log LOGGER = LogFactory.getLog(FileLink.class); private String fileType; + private final JabRefPreferences prefs; + public FileLink(JabRefPreferences prefs) { + this.prefs = prefs; + } + @Override public String format(String field) { if (field == null) { @@ -75,10 +81,10 @@ public String format(String field) { // but that is not available from a formatter. Therefore, as an // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: - if (Globals.prefs.fileDirForDatabase == null) { - dirs = Collections.singletonList(Globals.prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); + if (prefs.fileDirForDatabase == null) { + dirs = Collections.singletonList(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); } else { - dirs = Globals.prefs.fileDirForDatabase; + dirs = prefs.fileDirForDatabase; } Optional f = FileUtil.expandFilename(link, dirs); diff --git a/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java b/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java index 59a7a25ede5b..d0771933283a 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/JournalAbbreviator.java @@ -30,6 +30,7 @@ import java.util.Objects; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.layout.LayoutFormatter; /** @@ -50,14 +51,18 @@ public class JournalAbbreviator implements LayoutFormatter { private final JournalAbbreviationLoader repostioryLoader; + private final JournalAbbreviationPreferences journalAbbreviationPreferences; - public JournalAbbreviator(JournalAbbreviationLoader repostioryLoader) { + public JournalAbbreviator(JournalAbbreviationLoader repostioryLoader, + JournalAbbreviationPreferences journalAbbreviationPreferences) { this.repostioryLoader = Objects.requireNonNull(repostioryLoader); + this.journalAbbreviationPreferences = Objects.requireNonNull(journalAbbreviationPreferences); } @Override public String format(String fieldText) { - return repostioryLoader.getRepository().getIsoAbbreviation(fieldText).orElse(fieldText); + return repostioryLoader.getRepository(journalAbbreviationPreferences) + .getIsoAbbreviation(fieldText).orElse(fieldText); } } diff --git a/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java index 5f7812876622..1cc455bf7e1b 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java @@ -19,10 +19,10 @@ import java.util.List; import java.util.Map; -import net.sf.jabref.Globals; import net.sf.jabref.logic.bst.BibtexNameFormatter; import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.model.entry.AuthorList; +import net.sf.jabref.preferences.JabRefPreferences; /** * This layout formatter uses the Bibtex name.format$ method and provides ultimate flexibility: @@ -184,12 +184,12 @@ public void setParameter(String parameter) { this.parameter = parameter; } - public static Map getNameFormatters() { + public static Map getNameFormatters(JabRefPreferences prefs) { Map result = new HashMap<>(); - List names = Globals.prefs.getStringList(NameFormatter.NAME_FORMATER_KEY); - List formats = Globals.prefs.getStringList(NameFormatter.NAME_FORMATTER_VALUE); + List names = prefs.getStringList(NameFormatter.NAME_FORMATER_KEY); + List formats = prefs.getStringList(NameFormatter.NAME_FORMATTER_VALUE); for (int i = 0; i < names.size(); i++) { if (i < formats.size()) { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java index 426c2ecd0916..9920e60a55a6 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java @@ -29,6 +29,7 @@ import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -116,6 +117,7 @@ public class WrapFileLinks extends AbstractParamLayoutFormatter { // Define which escape sequences give what results: private static final Map ESCAPE_SEQ = new HashMap<>(); + private final JabRefPreferences prefs; static { WrapFileLinks.ESCAPE_SEQ.put('i', WrapFileLinks.ITERATION_COUNT); @@ -126,6 +128,11 @@ public class WrapFileLinks extends AbstractParamLayoutFormatter { WrapFileLinks.ESCAPE_SEQ.put('d', WrapFileLinks.FILE_DESCRIPTION); } + + public WrapFileLinks(JabRefPreferences prefs) { + this.prefs = prefs; + } + @Override public void setArgument(String arg) { String[] parts = AbstractParamLayoutFormatter.parseArgument(arg); @@ -170,10 +177,10 @@ public String format(String field) { // but that is not available from a formatter. Therefore, as an // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: - if (Globals.prefs.fileDirForDatabase == null) { - dirs = Collections.singletonList(Globals.prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); + if (prefs.fileDirForDatabase == null) { + dirs = Collections.singletonList(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); } else { - dirs = Globals.prefs.fileDirForDatabase; + dirs = prefs.fileDirForDatabase; } Optional f = FileUtil.expandFilename(flEntry.getLink(), dirs); diff --git a/src/main/java/net/sf/jabref/logic/net/URLDownload.java b/src/main/java/net/sf/jabref/logic/net/URLDownload.java index c6fbb6bc2b62..e942ebca67b8 100644 --- a/src/main/java/net/sf/jabref/logic/net/URLDownload.java +++ b/src/main/java/net/sf/jabref/logic/net/URLDownload.java @@ -36,8 +36,6 @@ import java.util.HashMap; import java.util.Map; -import net.sf.jabref.Globals; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -143,14 +141,10 @@ private URLConnection openConnection() throws IOException { } /** - * Encoding will be determined from JabRefPreferences.DEFAULT_ENCODING * * @return the downloaded string * @throws IOException */ - public String downloadToString() throws IOException { - return downloadToString(Globals.prefs.getDefaultEncoding()); - } public String downloadToString(Charset encoding) throws IOException { diff --git a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java index 7488671a7f1a..ff6a1255e3f7 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java @@ -36,7 +36,6 @@ import java.util.TreeSet; import java.util.regex.Pattern; -import net.sf.jabref.JabRefMain; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.layout.LayoutFormatter; @@ -46,6 +45,7 @@ import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -147,13 +147,16 @@ enum BibStyleMode { private static final String AUTHOR_SEPARATOR = "AuthorSeparator"; private final JournalAbbreviationLoader repositoryLoader; + private final JabRefPreferences prefs; private static final Pattern QUOTED = Pattern.compile("\".*\""); private static final Log LOGGER = LogFactory.getLog(OOBibStyle.class); - public OOBibStyle(File styleFile, JournalAbbreviationLoader repositoryLoader, Charset encoding) throws IOException { + public OOBibStyle(File styleFile, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader, + Charset encoding) throws IOException { this.repositoryLoader = Objects.requireNonNull(repositoryLoader); + this.prefs = Objects.requireNonNull(prefs); this.styleFile = Objects.requireNonNull(styleFile); this.encoding = Objects.requireNonNull(encoding); setDefaultProperties(); @@ -162,12 +165,13 @@ public OOBibStyle(File styleFile, JournalAbbreviationLoader repositoryLoader, Ch path = styleFile.getPath(); } - public OOBibStyle(String resourcePath, JournalAbbreviationLoader repositoryLoader) + public OOBibStyle(String resourcePath, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) throws IOException { this.repositoryLoader = Objects.requireNonNull(repositoryLoader); + this.prefs = Objects.requireNonNull(prefs); this.encoding = StandardCharsets.UTF_8; setDefaultProperties(); - initialize(JabRefMain.class.getResource(resourcePath).openStream()); + initialize(OOBibStyle.class.getResource(resourcePath).openStream()); fromResource = true; path = resourcePath; } @@ -378,7 +382,8 @@ private void handleStructureLine(String line) { boolean setDefault = line.substring(0, index).equals(OOBibStyle.DEFAULT_MARK); String type = line.substring(0, index); try { - Layout layout = new LayoutHelper(new StringReader(formatString), this.repositoryLoader).getLayoutFromText(); + Layout layout = new LayoutHelper(new StringReader(formatString), this.prefs, this.repositoryLoader) + .getLayoutFromText(); if (setDefault) { defaultBibLayout = layout; } else { diff --git a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java index af1a616d643e..1d0d1f5761a8 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java @@ -25,6 +25,7 @@ import java.util.Objects; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -43,6 +44,7 @@ public class StyleLoader { private final JournalAbbreviationLoader journalAbbreviationLoader; private final OpenOfficePreferences preferences; private final Charset encoding; + private final JabRefPreferences jabrefPreferences; // Lists of the internal // and external styles @@ -50,9 +52,11 @@ public class StyleLoader { private final List externalStyles = new ArrayList<>(); - public StyleLoader(OpenOfficePreferences preferences, JournalAbbreviationLoader journalAbbreviationLoader, Charset encoding) { + public StyleLoader(OpenOfficePreferences preferences, JabRefPreferences jabrefPreferences, + JournalAbbreviationLoader journalAbbreviationLoader, Charset encoding) { this.journalAbbreviationLoader = Objects.requireNonNull(journalAbbreviationLoader); this.preferences = Objects.requireNonNull(preferences); + this.jabrefPreferences = Objects.requireNonNull(jabrefPreferences); this.encoding = Objects.requireNonNull(encoding); loadInternalStyles(); loadExternalStyles(); @@ -72,7 +76,8 @@ public List getStyles() { public boolean addStyleIfValid(String filename) { Objects.requireNonNull(filename); try { - OOBibStyle newStyle = new OOBibStyle(new File(filename), journalAbbreviationLoader, encoding); + OOBibStyle newStyle = new OOBibStyle(new File(filename), jabrefPreferences, journalAbbreviationLoader, + encoding); if (externalStyles.contains(newStyle)) { LOGGER.info("External style file " + filename + " already existing."); } else if (newStyle.isValid()) { @@ -98,7 +103,8 @@ private void loadExternalStyles() { List lists = preferences.getExternalStyles(); for (String filename : lists) { try { - OOBibStyle style = new OOBibStyle(new File(filename), journalAbbreviationLoader, encoding); + OOBibStyle style = new OOBibStyle(new File(filename), jabrefPreferences, journalAbbreviationLoader, + encoding); if (style.isValid()) { //Problem! externalStyles.add(style); } else { @@ -117,7 +123,7 @@ private void loadInternalStyles() { internalStyles.clear(); for (String filename : internalStyleFiles) { try { - internalStyles.add(new OOBibStyle(filename, journalAbbreviationLoader)); + internalStyles.add(new OOBibStyle(filename, jabrefPreferences, journalAbbreviationLoader)); } catch (IOException e) { LOGGER.info("Problem reading internal style file " + filename, e); } 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 126d1d82a0fb..3bbc88c267d3 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 @@ -317,7 +317,8 @@ private static File shortenFileName(File fileName, String directory) { } } - public static Map> findAssociatedFiles(Collection entries, Collection extensions, Collection directories) { + public static Map> findAssociatedFiles(Collection entries, + Collection extensions, Collection directories, JabRefPreferences prefs) { Map> result = new HashMap<>(); // First scan directories @@ -328,7 +329,7 @@ public static Map> findAssociatedFiles(Collection result.put(entry, new ArrayList<>()); } - boolean exactOnly = Globals.prefs.getBoolean(JabRefPreferences.AUTOLINK_EXACT_KEY_ONLY); + boolean exactOnly = prefs.getBoolean(JabRefPreferences.AUTOLINK_EXACT_KEY_ONLY); // Now look for keys nextFile: for (File file : filesWithExtension) { @@ -392,12 +393,12 @@ public static List getListOfLinkedFiles(List bes, List f * @return a suggested fileName */ public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, - JournalAbbreviationLoader repositoryLoader) { + JournalAbbreviationLoader repositoryLoader, JabRefPreferences prefs) { String targetName = entry.getCiteKey() == null ? "default" : entry.getCiteKey(); - StringReader sr = new StringReader(Globals.prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)); + StringReader sr = new StringReader(prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)); Layout layout = null; try { - layout = new LayoutHelper(sr, repositoryLoader).getLayoutFromText(); + layout = new LayoutHelper(sr, prefs, repositoryLoader).getLayoutFromText(); } catch (IOException e) { LOGGER.info("Wrong format " + e.getMessage(), e); } diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index 23fed90a703f..d4280c0cfb2c 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -47,6 +47,7 @@ import net.sf.jabref.logic.TypedBibEntry; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.Author; @@ -93,8 +94,8 @@ public class XMPUtil { * @return BibtexEntryies found in the PDF or an empty list * @throws IOException */ - public static List readXMP(String filename) throws IOException { - return XMPUtil.readXMP(new File(filename)); + public static List readXMP(String filename, JabRefPreferences prefs) throws IOException { + return XMPUtil.readXMP(new File(filename), prefs); } /** @@ -137,10 +138,10 @@ public static void writeXMP(String filename, BibEntry entry, * Throws an IOException if the file cannot be read, so the user * than remove a lock or cancel the operation. */ - public static List readXMP(File file) throws IOException { + public static List readXMP(File file, JabRefPreferences prefs) throws IOException { List result = Collections.emptyList(); try (FileInputStream inputStream = new FileInputStream(file)) { - result = XMPUtil.readXMP(inputStream); + result = XMPUtil.readXMP(inputStream, prefs); } return result; } @@ -178,7 +179,7 @@ public static PDDocument loadWithAutomaticDecryption(InputStream inputStream) th * * @return list of BibEntries retrieved from the stream. May be empty, but never null */ - public static List readXMP(InputStream inputStream) + public static List readXMP(InputStream inputStream, JabRefPreferences prefs) throws IOException { List result = new LinkedList<>(); @@ -206,7 +207,7 @@ public static List readXMP(InputStream inputStream) for (XMPSchema schema : schemas) { XMPSchemaDublinCore dc = (XMPSchemaDublinCore) schema; - Optional entry = XMPUtil.getBibtexEntryFromDublinCore(dc); + Optional entry = XMPUtil.getBibtexEntryFromDublinCore(dc, prefs); if (entry.isPresent()) { if (entry.get().getType() == null) { @@ -234,8 +235,8 @@ public static List readXMP(InputStream inputStream) return result; } - public static Collection readXMP(Path filePath) throws IOException { - return readXMP(filePath.toFile()); + public static Collection readXMP(Path filePath, JabRefPreferences prefs) throws IOException { + return readXMP(filePath.toFile(), prefs); } /** @@ -312,7 +313,8 @@ public static Optional getBibtexEntryFromDocumentInformation( * * @return The bibtex entry found in the document information. */ - public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCore dcSchema) { + public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCore dcSchema, + JabRefPreferences prefs) { BibEntry entry = new BibEntry(); @@ -416,7 +418,7 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor */ List subjects = dcSchema.getSubjects(); if (subjects != null) { - entry.addKeywords(subjects); + entry.addKeywords(subjects, prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); } /** @@ -1187,9 +1189,10 @@ public static void main(String[] args) throws IOException, TransformerException if (args[0].endsWith(".pdf")) { // Read from pdf and write as BibTex - List l = XMPUtil.readXMP(new File(args[0])); + List l = XMPUtil.readXMP(new File(args[0]), Globals.prefs); - BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new LatexFieldFormatter(), false); + BibEntryWriter bibtexEntryWriter = new BibEntryWriter( + new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)), false); for (BibEntry entry : l) { StringWriter sw = new StringWriter(); @@ -1274,9 +1277,9 @@ public static void main(String[] args) throws IOException, TransformerException /** * see XMPUtil.hasMetadata(InputStream) */ - public static boolean hasMetadata(Path path) { + public static boolean hasMetadata(Path path, JabRefPreferences prefs) { try (InputStream inputStream = Files.newInputStream(path, StandardOpenOption.READ)) { - return hasMetadata(inputStream); + return hasMetadata(inputStream, prefs); } catch (IOException e) { LOGGER.error("XMP reading failed", e); return false; @@ -1294,9 +1297,9 @@ public static boolean hasMetadata(Path path) { * The inputStream to read the PDF from. * @return whether a BibEntry was found in the given PDF. */ - public static boolean hasMetadata(InputStream inputStream) { + public static boolean hasMetadata(InputStream inputStream, JabRefPreferences prefs) { try { - List bibEntries = XMPUtil.readXMP(inputStream); + List bibEntries = XMPUtil.readXMP(inputStream, prefs); return !bibEntries.isEmpty(); } catch (EncryptedPdfsNotSupportedException ex) { LOGGER.info("Encryption not supported by XMPUtil"); diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index 9ac64bd51929..a25fb942570a 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -34,11 +34,9 @@ import java.util.Set; import java.util.TreeSet; -import net.sf.jabref.Globals; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.event.FieldChangedEvent; -import net.sf.jabref.preferences.JabRefPreferences; import com.google.common.base.Strings; import com.google.common.eventbus.EventBus; @@ -539,7 +537,7 @@ public void setChanged(boolean changed) { this.changed = changed; } - public Optional putKeywords(Collection keywords) { + public Optional putKeywords(Collection keywords, String separator) { Objects.requireNonNull(keywords); Optional oldValue = this.getFieldOptional(KEYWORDS_FIELD); @@ -553,7 +551,7 @@ public Optional putKeywords(Collection keywords) { } // Set new keyword field - String newValue = String.join(Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR), keywords); + String newValue = String.join(separator, keywords); return this.setField(KEYWORDS_FIELD, newValue); } @@ -562,7 +560,7 @@ public Optional putKeywords(Collection keywords) { * * @param keyword Keyword to add */ - public void addKeyword(String keyword) { + public void addKeyword(String keyword, String separator) { Objects.requireNonNull(keyword, "keyword must not be null"); if (keyword.isEmpty()) { @@ -571,7 +569,7 @@ public void addKeyword(String keyword) { Set keywords = this.getKeywords(); keywords.add(keyword); - this.putKeywords(keywords); + this.putKeywords(keywords, separator); } /** @@ -579,11 +577,11 @@ public void addKeyword(String keyword) { * * @param keywords Keywords to add */ - public void addKeywords(Collection keywords) { + public void addKeywords(Collection keywords, String separator) { Objects.requireNonNull(keywords); for (String keyword : keywords) { - this.addKeyword(keyword); + this.addKeyword(keyword, separator); } } diff --git a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index c584b1aee724..ccb09d167c5a 100644 --- a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -43,7 +43,6 @@ import java.util.Set; import net.sf.jabref.Globals; -import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; public class InternalBibtexFields { @@ -78,9 +77,11 @@ public class InternalBibtexFields { public static final List BIBLATEX_PAGINATION_FIELDS = Arrays.asList("pagination", "bookpagination"); // singleton instance - private static final InternalBibtexFields RUNTIME = new InternalBibtexFields(); + private static final InternalBibtexFields RUNTIME = new InternalBibtexFields( + Globals.prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS)); - private InternalBibtexFields() { + + private InternalBibtexFields(boolean serializeSpecialFields) { fieldSet = new HashMap<>(); BibtexSingleField dummy; @@ -131,42 +132,42 @@ private InternalBibtexFields() { // custom fields not displayed at editor, but as columns in the UI dummy = new BibtexSingleField(SpecialFieldsUtils.FIELDNAME_RANKING, false); - if (!Globals.prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS)) { + if (!serializeSpecialFields) { dummy.setPrivate(); dummy.setWriteable(false); dummy.setDisplayable(false); } add(dummy); dummy = new BibtexSingleField(SpecialFieldsUtils.FIELDNAME_PRIORITY, false); - if (!Globals.prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS)) { + if (!serializeSpecialFields) { dummy.setPrivate(); dummy.setWriteable(false); dummy.setDisplayable(false); } add(dummy); dummy = new BibtexSingleField(SpecialFieldsUtils.FIELDNAME_RELEVANCE, false); - if (!Globals.prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS)) { + if (!serializeSpecialFields) { dummy.setPrivate(); dummy.setWriteable(false); dummy.setDisplayable(false); } add(dummy); dummy = new BibtexSingleField(SpecialFieldsUtils.FIELDNAME_QUALITY, false); - if (!Globals.prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS)) { + if (!serializeSpecialFields) { dummy.setPrivate(); dummy.setWriteable(false); dummy.setDisplayable(false); } add(dummy); dummy = new BibtexSingleField(SpecialFieldsUtils.FIELDNAME_READ, false); - if (!Globals.prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS)) { + if (!serializeSpecialFields) { dummy.setPrivate(); dummy.setWriteable(false); dummy.setDisplayable(false); } add(dummy); dummy = new BibtexSingleField(SpecialFieldsUtils.FIELDNAME_PRINTED, false); - if (!Globals.prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS)) { + if (!serializeSpecialFields) { dummy.setPrivate(); dummy.setWriteable(false); dummy.setDisplayable(false); @@ -321,8 +322,7 @@ private InternalBibtexFields() { * sorting for all fields listed in the array. If an unknown field name is included, * add a field descriptor for the new field. */ - public static void setNumericFieldsFromPrefs() { - List numFields = Globals.prefs.getStringList(JabRefPreferences.NUMERIC_FIELDS); + public static void setNumericFields(List numFields) { if (numFields.isEmpty()) { return; } diff --git a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java index 818a41045762..53fbc520690d 100644 --- a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java +++ b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java @@ -58,8 +58,8 @@ public class PdfImporter { private final JabRefFrame frame; private final BasePanel panel; - private MainTable entryTable; - private int dropRow; + private final MainTable entryTable; + private final int dropRow; private static final Log LOGGER = LogFactory.getLog(PdfImporter.class); @@ -149,7 +149,7 @@ private List importPdfFiles(List fileNames) { for (String fileName : fileNames) { if (!neverShow && !doNotShowAgain) { importDialog = new ImportDialog(dropRow >= 0, fileName); - if (!XMPUtil.hasMetadata(Paths.get(fileName))) { + if (!XMPUtil.hasMetadata(Paths.get(fileName), Globals.prefs)) { importDialog.disableXMPChoice(); } importDialog.setLocationRelativeTo(frame); @@ -250,7 +250,8 @@ private void doContentImport(String fileName, List res) { // insert entry to database and link file panel.getDatabase().insertEntry(entry); panel.markBaseChanged(); - LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry); + LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry, + Globals.prefs); DroppedFileHandler dfh = new DroppedFileHandler(frame, panel); dfh.linkPdfToEntry(fileName, entry); panel.highlightEntry(entry); diff --git a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java index 33868186da60..dd299ab52b42 100644 --- a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java @@ -338,7 +338,6 @@ public class JabRefPreferences { public static final String CUSTOM_TAB_FIELDS = "customTabFields_"; public static final String USE_UNIT_FORMATTER_ON_SEARCH = "useUnitFormatterOnSearch"; public static final String USE_CASE_KEEPER_ON_SEARCH = "useCaseKeeperOnSearch"; - 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"; @@ -862,7 +861,6 @@ private JabRefPreferences() { defaults.put(REG_EXP_SEARCH_EXPRESSION_KEY, defaultExpression); defaults.put(AUTOLINK_USE_REG_EXP_SEARCH_KEY, Boolean.FALSE); defaults.put(USE_IEEE_ABRV, Boolean.FALSE); - defaults.put(USE_CONVERT_TO_EQUATION, Boolean.FALSE); defaults.put(USE_CASE_KEEPER_ON_SEARCH, Boolean.TRUE); defaults.put(USE_UNIT_FORMATTER_ON_SEARCH, Boolean.TRUE); defaults.put(MAX_BACK_HISTORY_SIZE, 10); diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java index 731ecddcddae..940cd3302b13 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java @@ -27,6 +27,7 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.preferences.JabRefPreferences; import static net.sf.jabref.model.entry.BibEntry.KEYWORDS_FIELD; @@ -121,7 +122,8 @@ private static void exportFieldToKeywords(SpecialField e, String newValue, BibEn } - Optional change = entry.putKeywords(keywordList); + Optional change = entry.putKeywords(keywordList, + Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); if (ce != null){ change.ifPresent(changeValue -> ce.addEdit(new UndoableFieldChange(changeValue))); } diff --git a/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java b/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java index 34a5ac3382a1..036d6778eb61 100644 --- a/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java +++ b/src/main/java/net/sf/jabref/sql/importer/DatabaseImporter.java @@ -31,6 +31,7 @@ import java.util.StringJoiner; import java.util.stream.Collectors; +import net.sf.jabref.Globals; import net.sf.jabref.MetaData; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.logic.groups.AbstractGroup; @@ -228,7 +229,7 @@ private void importGroupsTree(MetaData metaData, Map entries, break; case ExplicitGroup.ID: group = new ExplicitGroup(rsGroups.getString("label"), - GroupHierarchyType.getByNumber(rsGroups.getInt("hierarchical_context"))); + GroupHierarchyType.getByNumber(rsGroups.getInt("hierarchical_context")), Globals.prefs); break; case KeywordGroup.ID: LOGGER.debug("Keyw: " + rsGroups.getBoolean("case_sensitive")); @@ -236,7 +237,7 @@ private void importGroupsTree(MetaData metaData, Map entries, StringUtil.unquote(rsGroups.getString("search_field"), '\\'), StringUtil.unquote(rsGroups.getString("search_expression"), '\\'), rsGroups.getBoolean("case_sensitive"), rsGroups.getBoolean("reg_exp"), - GroupHierarchyType.getByNumber(rsGroups.getInt("hierarchical_context"))); + GroupHierarchyType.getByNumber(rsGroups.getInt("hierarchical_context")), Globals.prefs); break; case SearchGroup.ID: LOGGER.debug("Search: " + rsGroups.getBoolean("case_sensitive")); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 1f09d720a84d..67f68b2c23b1 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1226,7 +1226,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= Please_enter_a_search_string= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 853948a7bc8a..dee230addbb7 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1934,7 +1934,6 @@ Searching...=Suche_läuft... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Sie_haben_mehr_als_%0_Einträge_zum_Download_ausgewählt._Einige_Webseiten_könnten_zu_viele_Downloads_blockieren._Möchten_Sie_fortfahren? Confirm_selection=Auswahl_bestätigen Unknown_DOI\:_'%0'.=Unbekannte_DOI\:_'0%'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Hoch-_und_tiefgestellte_Zeichen_in_eine_Gleichung_konvertieren_und_nicht_als_Text_darstellen Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Nach_der_Suche_{}_zu_festgesetzten_Titelworten_hinzufügen,_um_Groß-/Kleinschreibung_beizubehalten Import_conversions=Konvertierungen_importieren Please_enter_a_search_string=Bitte_geben_Sie_eine_Suchphrase_ein diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 2e2d6dff0b85..1d87886261e6 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1832,7 +1832,6 @@ Searching...=Searching... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue? Confirm_selection=Confirm_selection Unknown_DOI\:_'%0'.=Unknown_DOI\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case Import_conversions=Import_conversions Please_enter_a_search_string=Please_enter_a_search_string diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index a7c6884fe269..d3ba5a7bec08 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1134,7 +1134,6 @@ Searching...=Buscando... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Ha_seleccionado_más_de_%0_entradas_para_descargar._Algunos_sitios_web_podrían_bloquearle_si_hace_demasiadas_descargas._¿Desea_continuar? Confirm_selection=Confirmar_selección Unknown_DOI\:_'%0'.=DOI_desconocido\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Preferir_convertir_subíndices_y_superíndices_a_ecuaciónantes_que_a_texto Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Añadir_{}_para_especificar_las_palabras_del_título_para_mantener_mayúsculas/minúsculas_correctamente Import_conversions=Importar_conversiones Please_enter_a_search_string=Introduzca_una_cadena_de_búsqueda,_por_favor diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 2e92ec35fda2..2d051c0c7221 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1888,7 +1888,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= Please_enter_a_search_string= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 576a040f542f..649d1d731ef7 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1166,7 +1166,6 @@ Searching...=Recherche... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Vous_avez_sélectionné_plus_de_%0_entrées_à_télécharger._Certains_sites_web_pourraient_vous_bloquer_si_vous_effectuez_de_trop_nombreux_et_rapides_téléchargements._Voulez-vous_continuer? Confirm_selection=Confirmez_la_sélection Unknown_DOI\:_'%0'.=DOI_inconnu_\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Conversion_des_indices_et_exposants_en_équations_plutôt_qu'en_texte Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Ajouter_{}_aux_mots_du_titre_spécifiés_lors_d'une_recherche_pour_préserver_la_casse_correcte Import_conversions=Importer_les_conversions Please_enter_a_search_string=Entrez_s'il_vous_plait_une_chaine_de_recherche diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 24a7595923e5..3b8b2b2f8183 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1143,7 +1143,6 @@ Searching...=Sedang_mencari... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Anda_memilih_lebih_dari_%0_entri._Sejumlah_situs_web_akan_memblokir_anda_kalau_melakukan_terlalu_banyak_pemuatturunan_dengan_cepat._Apa_mau_teruskan? Confirm_selection=Mengkonfirmasi_pilihan Unknown_DOI\:_'%0'.=DOI_tidak_dikenal\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions=Impor_konversi Please_enter_a_search_string=Tuliskan_string_pencarian diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 3ae8e350e86b..b9a6561346df 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1244,7 +1244,6 @@ Searching...=Ricerca_in_corso... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Sono_state_selezionate_pi\u00f9_di_%0_voci_da_scaricare._Alcuni_siti_potrebbero_bloccare_la_connessione_se_si_eseguono_scaricamenti_troppo_numerosi_e_rapidi._Continuare? Confirm_selection=Conferma_la_selezione Unknown_DOI\:_'%0'.=DOI_sconosciuto\:_'%0' -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Conversione_di_apici_e_pedici_in_equazioni_piuttosto_che_in_testo. Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Aggiungere_{}_alle_parole_del_titolo_specificate_per_mantenere_la_corretta_capitalizzazione_nella_ricerca. Import_conversions=Importare_le_conversioni Please_enter_a_search_string=Inserire_una_stringa_di_ricerca diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index b1e8d314abba..d6cbde88f906 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1915,7 +1915,6 @@ Searching...=検索中... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=ダウンロードする項目を%0個以上選択しました。あまりに多くのダウンロードを急に行うと、其れをブロックするウェブサイトもあります。続けますか? Confirm_selection=選択範囲を確認 Unknown_DOI\:_'%0'.=「%0」は既知のDOIではありません -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=上添字及び下添字をテキストではなく数式に変換する Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=大小文字を正しく維持するため、検索中に指定したタイトル語に{}を付け加える Import_conversions=読み込み時変換 Please_enter_a_search_string=検索文字列を入力してください diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 19016e7e6952..95b71fe05df8 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1917,7 +1917,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.=Unbekende_DOI\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= Please_enter_a_search_string= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index e5747132d9bb..fb3d3e1f6e00 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2312,7 +2312,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= Please_enter_a_search_string= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 415dd4be244a..d9d4e1aaf9ba 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1141,7 +1141,6 @@ Searching...=Buscando... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Você_selecionou_mais_de_%0_entradas_para_download._Alguns_sites_podem_bloquear_seu_acesso_se_você_fizer_muitos_downloads_num_período_curto_de_tempo._Deseja_continuar_mesmo_assim? Confirm_selection=Confirmar_seleção Unknown_DOI\:_'%0'.=DOI_desconhecido\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Dar_preferência_à_conversão_de_subscritos_sobrescritos_para_equações_ao_invés_de_textos Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Adicione_{}_às_palavras_do_título_na_busca_para_manter_maiúsculas_minúsculas Import_conversions=Importar_conversões Please_enter_a_search_string=Favor_digitar_uma_string_de_busca diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 8e36e2193b40..578b1a8e65de 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1885,7 +1885,6 @@ Searching...=Выполняется_поиск... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=Выбрано_более_%0_записей_для_загрузки._Возможна_блокировка_пользователя_некоторыми_веб-сайтами_при_большом_числе_быстрых_загрузок._Продолжить? Confirm_selection=Подтвердить_выбор Unknown_DOI\:_'%0'.=Неизвестный_DOI\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Преобразовывать_надстрочный_и_подстрочный_индекс_в_формулу_вместо_текста Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Добавлять_{}_к_указанным_заглавным_словам_при_поиске_для_соблюдения_правильности_регистра Import_conversions=Импорт_преобразований Please_enter_a_search_string=Введите_строку_для_поиска diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 6c2ba56626f8..8e618bc4a72c 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -867,7 +867,6 @@ Possible_duplicate_entries=Möjliga_dubbletter Possible_duplicate_of_existing_entry._Click_to_resolve.=Möjlig_dubblett_av_befintlig_post._Klicka_för_att_reda_ut. Preamble=Preamble Preamble_editor,_store_changes=Preamble-editorn,_spara_ändringar -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Preferences=Inställningar Preferences_recorded.=Inställningar_sparade. Preview=Postvisning diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 7ae734f66d78..daa1a5b68b8e 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1163,7 +1163,6 @@ Searching...=Arıyor... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?=İndirmek_için_%0'dan_fazla_girdi_seçtiniz._Çok_sayıda_hızlı_indirme_yaparsanız_bazı_web_siteleri_sizi_bloke_edebilir._Devam_etmek_istiyor_musunuz? Confirm_selection=Seçimi_onayla Unknown_DOI\:_'%0'.=Bilinmeyen_DOI\:_'%0'. -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=Alt_ve_üstsimgeleri_metinden_ziyade_denklemlere_dönüştürmeyi_tercih_et Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=Aramada_doğru_küçük_büyük_harf_seçimi_için_belirli_başlık_sözcüklerine_{}_ekleyin Import_conversions=Dönüşümleri_içe_aktar Please_enter_a_search_string=Lütfen_bir_arama_dizgesi_girin diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 78865a76a746..8287ab5aaab2 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1911,7 +1911,6 @@ Searching...= You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection= Unknown_DOI\:_'%0'.= -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text= Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case= Import_conversions= Please_enter_a_search_string= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 0292f2f0fea7..e8949a25a47a 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1217,7 +1217,6 @@ Searching...=正在搜索... You_have_selected_more_than_%0_entries_for_download._Some_web_sites_might_block_you_if_you_make_too_many_rapid_downloads._Do_you_want_to_continue?= Confirm_selection=确认选择 Unknown_DOI\:_'%0'.= -Prefer_converting_subscripts_and_superscripts_to_equations_rather_than_text=将上下标转换成公式而不是文本 Add_{}_to_specified_title_words_on_search_to_keep_the_correct_case=搜索时为特殊的标题单词添加_{}_以保证大小写正确 Import_conversions=导入约定 Please_enter_a_search_string=请输入一个搜索字符串 diff --git a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java index f5cd24a89c86..500b77e4b07f 100644 --- a/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java +++ b/src/test/java/net/sf/jabref/importer/ConvertLegacyExplicitGroupsTest.java @@ -34,7 +34,7 @@ public void setUp() throws Exception { entry = new BibEntry(); entry.setCiteKey("Entry1"); - group = new ExplicitGroup("TestGroup", GroupHierarchyType.INCLUDING); + group = new ExplicitGroup("TestGroup", GroupHierarchyType.INCLUDING, Globals.prefs); group.addLegacyEntryKey("Entry1"); } @@ -59,7 +59,7 @@ public void performActionClearsLegacyKeys() throws Exception { @Test public void performActionWritesGroupMembershipInEntryForComplexGroupTree() throws Exception { GroupTreeNode root = GroupTreeNode.fromGroup(new AllEntriesGroup()); - root.addSubgroup(new ExplicitGroup("TestGroup2", GroupHierarchyType.INCLUDING)); + root.addSubgroup(new ExplicitGroup("TestGroup2", GroupHierarchyType.INCLUDING, Globals.prefs)); root.addSubgroup(group); ParserResult parserResult = generateParserResult(entry, root); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java index c5d77dc8f8ab..b6beedd24fb2 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/BibtexParserTest.java @@ -1393,7 +1393,7 @@ public void integrationTestCustomKeyPattern() throws IOException { AbstractLabelPattern labelPattern = result.getMetaData().getLabelPattern(); - AbstractLabelPattern expectedPattern = new DatabaseLabelPattern(); + AbstractLabelPattern expectedPattern = new DatabaseLabelPattern(Globals.prefs); expectedPattern.setDefaultValue("test"); expectedPattern.addLabelPattern("article", "articleTest"); @@ -1430,10 +1430,12 @@ public void integrationTestGroupTree() throws IOException, ParseException { assertEquals(new AllEntriesGroup(), root.getGroup()); assertEquals(3, root.getNumberOfChildren()); assertEquals( - new KeywordGroup("Fréchet", "keywords", "FrechetSpace", false, true, GroupHierarchyType.INDEPENDENT), + new KeywordGroup("Fréchet", "keywords", "FrechetSpace", false, true, GroupHierarchyType.INDEPENDENT, + Globals.prefs), root.getChildren().get(0).getGroup()); assertEquals( - new KeywordGroup("Invariant theory", "keywords", "GIT", false, false, GroupHierarchyType.INDEPENDENT), + new KeywordGroup("Invariant theory", "keywords", "GIT", false, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs), root.getChildren().get(1).getGroup()); assertEquals(Arrays.asList("Key1", "Key2"), ((ExplicitGroup) root.getChildren().get(2).getGroup()).getLegacyEntryKeys()); } diff --git a/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java b/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java index 5c2d8eddd127..61b9c6080f0f 100644 --- a/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java +++ b/src/test/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactoryTest.java @@ -1,6 +1,8 @@ package net.sf.jabref.logic.autocompleter; +import net.sf.jabref.Globals; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Assert; import org.junit.Before; @@ -17,6 +19,7 @@ public class AutoCompleterFactoryTest { public void setUp() throws Exception { AutoCompletePreferences preferences = mock(AutoCompletePreferences.class); abbreviationLoader = mock(JournalAbbreviationLoader.class); + Globals.prefs = JabRefPreferences.getInstance(); autoCompleterFactory = new AutoCompleterFactory(preferences, abbreviationLoader); } diff --git a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java index e8fcbc0ca7f9..15aa1ff65684 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java @@ -39,7 +39,8 @@ public static void tearDown() { @Before public void setUpWriter() { - writer = new BibEntryWriter(new LatexFieldFormatter(), true); + writer = new BibEntryWriter( + new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)), true); } @Test diff --git a/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java b/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java index 47a8fd30d363..2af06571390b 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/FieldContentParserTest.java @@ -20,7 +20,7 @@ public static void loadPreferences() { @Before public void setUp() throws Exception { - parser = new FieldContentParser(); + parser = new FieldContentParser(FieldContentParserPreferences.fromPreferences(Globals.prefs)); } @Test diff --git a/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java b/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java index 815e2c14afea..ba17d60329d9 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/LatexFieldFormatterTests.java @@ -20,7 +20,7 @@ public static void setUpBeforeClass(){ @Before public void setUp() { - this.formatter = new LatexFieldFormatter(); + this.formatter = new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)); } @Test diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java index 4fef99dfbbef..91d81b055b53 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -59,7 +59,7 @@ public void setUp() throws IOException { MetaData metaData = new MetaData(); metaData.setDefaultFileDirectory(pdfFolder.getAbsolutePath()); BibDatabaseContext context = new BibDatabaseContext(new BibDatabase(), metaData, bibFolder.newFile("test.bib")); - worker = new CleanupWorker(context, mock(JournalAbbreviationLoader.class)); + worker = new CleanupWorker(context, mock(JournalAbbreviationLoader.class), Globals.prefs); } diff --git a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java index 3af235826000..8e49feb10109 100644 --- a/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java +++ b/src/test/java/net/sf/jabref/logic/cleanup/RenamePdfCleanupTest.java @@ -54,7 +54,8 @@ public void cleanupRenamePdfRenamesFileEvenIfOnlyDifferenceIsCase() throws IOExc ParsedFileField fileField = new ParsedFileField("", tempFile.getAbsolutePath(), ""); entry.setField("file", FileField.getStringRepresentation(fileField)); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class), + Globals.prefs); cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot.tmp", ""); @@ -70,7 +71,8 @@ public void cleanupRenamePdfRenamesWithMultipleFiles() throws IOException { entry.setField("file", FileField.getStringRepresentation(Arrays.asList(new ParsedFileField("","",""), new ParsedFileField("", tempFile.getAbsolutePath(), ""), new ParsedFileField("","","")))); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class), + Globals.prefs); cleanup.cleanup(entry); assertEquals( @@ -87,7 +89,8 @@ public void cleanupRenamePdfRenamesFileStartingWithBibtexKey() throws IOExceptio entry.setField("file", FileField.getStringRepresentation(fileField)); entry.setField("title", "test title"); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class), + Globals.prefs); cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot - test title.tmp", ""); @@ -102,7 +105,8 @@ public void cleanupRenamePdfRenamesFileInSameFolder() throws IOException { entry.setField("file", FileField.getStringRepresentation(fileField)); entry.setField("title", "test title"); - RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class)); + RenamePdfCleanup cleanup = new RenamePdfCleanup(false, context, mock(JournalAbbreviationLoader.class), + Globals.prefs); cleanup.cleanup(entry); ParsedFileField newFileField = new ParsedFileField("", "Toot - test title.pdf", "PDF"); diff --git a/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java b/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java index aa597b1d4a46..807b51c71b90 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -155,7 +155,7 @@ public void writeEpilogueAndEncoding() throws Exception { @Test public void writeMetadata() throws Exception { - DatabaseLabelPattern labelPattern = new DatabaseLabelPattern(); + DatabaseLabelPattern labelPattern = new DatabaseLabelPattern(Globals.prefs); labelPattern.setDefaultValue("test"); metaData.setLabelPattern(labelPattern); @@ -168,7 +168,7 @@ public void writeMetadata() throws Exception { @Test public void writeMetadataAndEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); - DatabaseLabelPattern labelPattern = new DatabaseLabelPattern(); + DatabaseLabelPattern labelPattern = new DatabaseLabelPattern(Globals.prefs); labelPattern.setDefaultValue("test"); metaData.setLabelPattern(labelPattern); @@ -182,7 +182,7 @@ public void writeMetadataAndEncoding() throws Exception { @Test public void writeGroups() throws Exception { GroupTreeNode groupRoot = GroupTreeNode.fromGroup(new AllEntriesGroup()); - groupRoot.addSubgroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING)); + groupRoot.addSubgroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING, Globals.prefs)); metaData.setGroups(groupRoot); StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), new SavePreferences()); @@ -201,7 +201,8 @@ public void writeGroupsAndEncoding() throws Exception { SavePreferences preferences = new SavePreferences().withEncoding(Charsets.US_ASCII); GroupTreeNode groupRoot = GroupTreeNode.fromGroup(new AllEntriesGroup()); - groupRoot.addChild(GroupTreeNode.fromGroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING))); + groupRoot.addChild( + GroupTreeNode.fromGroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING, Globals.prefs))); metaData.setGroups(groupRoot); StringSaveSession session = databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList(), preferences); @@ -420,7 +421,7 @@ public void writeSaveOrderConfig() throws Exception { @Test public void writeCustomKeyPattern() throws Exception { - AbstractLabelPattern pattern = new DatabaseLabelPattern(); + AbstractLabelPattern pattern = new DatabaseLabelPattern(Globals.prefs); pattern.setDefaultValue("test"); pattern.addLabelPattern("article", "articleTest"); metaData.setLabelPattern(pattern); diff --git a/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java index d180b377294d..cd3800762c7a 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/ExportFormatTest.java @@ -78,7 +78,7 @@ public void testExportingNullEntriesThrowsNPE() throws Exception { public static Collection exportFormats() { Collection result = new ArrayList<>(); Globals.prefs = JabRefPreferences.getInstance(); - ExportFormats.initAllExports(); + ExportFormats.initAllExports(Globals.prefs.customExports.getCustomExportFormats(Globals.prefs)); for (IExportFormat format : ExportFormats.getExportFormats().values()) { result.add(new Object[] {format, format.getDisplayName()}); } diff --git a/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java b/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java index 19fb08598f44..2ff764799cec 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/HtmlExportFormatTest.java @@ -35,7 +35,7 @@ public class HtmlExportFormatTest { @Before public void setUp() { Globals.prefs = JabRefPreferences.getInstance(); - ExportFormats.initAllExports(); + ExportFormats.initAllExports(Globals.prefs.customExports.getCustomExportFormats(Globals.prefs)); exportFormat = ExportFormats.getExportFormat("html"); Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(); diff --git a/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java index 35f33e51da49..0d85b07ea189 100644 --- a/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/ExplicitGroupTest.java @@ -21,13 +21,13 @@ public void setUp() { @Test public void testToStringSimple() throws ParseException { - ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT); + ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); assertEquals("ExplicitGroup:myExplicitGroup;0;", group.toString()); } @Test public void toStringDoesNotWriteAssignedEntries() throws ParseException { - ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INCLUDING); + ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INCLUDING, Globals.prefs); group.add(makeBibtexEntry()); assertEquals("ExplicitGroup:myExplicitGroup;2;", group.toString()); } diff --git a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java index 3b48d6869408..a357b0598f27 100644 --- a/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/GroupTreeNodeTest.java @@ -21,7 +21,7 @@ public class GroupTreeNodeTest { - private List entries = new ArrayList<>(); + private final List entries = new ArrayList<>(); private BibEntry entry; @Before @@ -44,9 +44,11 @@ public void setUp() throws Exception { * B ExplicitNode, Refining (<-- this) */ private GroupTreeNode getNodeInSimpleTree(GroupTreeNode root) throws ParseException { - root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING)); - GroupTreeNode parent = root.addSubgroup(new ExplicitGroup("ExplicitParent", GroupHierarchyType.INDEPENDENT)); - GroupTreeNode node = parent.addSubgroup(new ExplicitGroup("ExplicitNode", GroupHierarchyType.REFINING)); + root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING, Globals.prefs)); + GroupTreeNode parent = root + .addSubgroup(new ExplicitGroup("ExplicitParent", GroupHierarchyType.INDEPENDENT, Globals.prefs)); + GroupTreeNode node = parent + .addSubgroup(new ExplicitGroup("ExplicitNode", GroupHierarchyType.REFINING, Globals.prefs)); return node; } @@ -73,8 +75,9 @@ private GroupTreeNode getNodeInSimpleTree() throws ParseException { */ private GroupTreeNode getNodeInComplexTree(GroupTreeNode root) throws ParseException { root.addSubgroup(getSearchGroup("SearchA")); - root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING)); - GroupTreeNode grandParent = root.addSubgroup(new ExplicitGroup("ExplicitGrandParent", GroupHierarchyType.INDEPENDENT)); + root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING, Globals.prefs)); + GroupTreeNode grandParent = root + .addSubgroup(new ExplicitGroup("ExplicitGrandParent", GroupHierarchyType.INDEPENDENT, Globals.prefs)); root.addSubgroup(getKeywordGroup("KeywordA")); grandParent.addSubgroup(getExplict("ExplicitB")); @@ -92,7 +95,8 @@ private GroupTreeNode getNodeInComplexTree(GroupTreeNode root) throws ParseExcep } private AbstractGroup getKeywordGroup(String name) throws ParseException { - return new KeywordGroup(name, "searchField", "searchExpression", true, false, GroupHierarchyType.INDEPENDENT); + return new KeywordGroup(name, "searchField", "searchExpression", true, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs); } private AbstractGroup getSearchGroup(String name) { @@ -100,7 +104,7 @@ private AbstractGroup getSearchGroup(String name) { } private AbstractGroup getExplict(String name) throws ParseException { - return new ExplicitGroup(name, GroupHierarchyType.REFINING); + return new ExplicitGroup(name, GroupHierarchyType.REFINING, Globals.prefs); } /* @@ -171,14 +175,16 @@ public void getTreeAsStringInComplexTree() throws Exception { @Test public void getSearchRuleForIndependentGroupReturnsGroupAsMatcher() throws ParseException { - GroupTreeNode node = GroupTreeNode.fromGroup(new ExplicitGroup("node", GroupHierarchyType.INDEPENDENT)); + GroupTreeNode node = GroupTreeNode + .fromGroup(new ExplicitGroup("node", GroupHierarchyType.INDEPENDENT, Globals.prefs)); assertEquals(node.getGroup(), node.getSearchRule()); } @Test public void getSearchRuleForRefiningGroupReturnsParentAndGroupAsMatcher() throws ParseException { - GroupTreeNode parent = GroupTreeNode.fromGroup(new ExplicitGroup("parent", GroupHierarchyType.INDEPENDENT)); - GroupTreeNode node = parent.addSubgroup(new ExplicitGroup("node", GroupHierarchyType.REFINING)); + GroupTreeNode parent = GroupTreeNode + .fromGroup(new ExplicitGroup("parent", GroupHierarchyType.INDEPENDENT, Globals.prefs)); + GroupTreeNode node = parent.addSubgroup(new ExplicitGroup("node", GroupHierarchyType.REFINING, Globals.prefs)); AndMatcher matcher = new AndMatcher(); matcher.addRule(node.getGroup()); @@ -188,8 +194,10 @@ public void getSearchRuleForRefiningGroupReturnsParentAndGroupAsMatcher() throws @Test public void getSearchRuleForIncludingGroupReturnsGroupOrSubgroupAsMatcher() throws ParseException { - GroupTreeNode node = GroupTreeNode.fromGroup(new ExplicitGroup("node", GroupHierarchyType.INCLUDING)); - GroupTreeNode child = node.addSubgroup(new ExplicitGroup("child", GroupHierarchyType.INDEPENDENT)); + GroupTreeNode node = GroupTreeNode + .fromGroup(new ExplicitGroup("node", GroupHierarchyType.INCLUDING, Globals.prefs)); + GroupTreeNode child = node + .addSubgroup(new ExplicitGroup("child", GroupHierarchyType.INDEPENDENT, Globals.prefs)); OrMatcher matcher = new OrMatcher(); matcher.addRule(node.getGroup()); @@ -206,7 +214,8 @@ public void numberOfHitsReturnsZeroForEmptyList() throws Exception { public void numberOfHitsMatchesOneEntry() throws Exception { GroupTreeNode parent = getNodeInSimpleTree(); GroupTreeNode node = parent.addSubgroup( - new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT)); + new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs)); assertEquals(1, node.numberOfHits(entries)); } @@ -214,7 +223,8 @@ public void numberOfHitsMatchesOneEntry() throws Exception { public void numberOfHitsMatchesMultipleEntries() throws Exception { GroupTreeNode parent = getNodeInSimpleTree(); GroupTreeNode node = parent.addSubgroup( - new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.INDEPENDENT)); + new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs)); assertEquals(2, node.numberOfHits(entries)); } @@ -222,9 +232,10 @@ public void numberOfHitsMatchesMultipleEntries() throws Exception { public void numberOfHitsWorksForRefiningGroups() throws Exception { GroupTreeNode grandParent = getNodeInSimpleTree(); GroupTreeNode parent = grandParent.addSubgroup( - new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT)); + new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs)); GroupTreeNode node = parent.addSubgroup( - new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.REFINING)); + new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.REFINING, Globals.prefs)); assertEquals(1, node.numberOfHits(entries)); } @@ -232,16 +243,18 @@ public void numberOfHitsWorksForRefiningGroups() throws Exception { public void numberOfHitsWorksForHierarchyOfIndependentGroups() throws Exception { GroupTreeNode grandParent = getNodeInSimpleTree(); GroupTreeNode parent = grandParent.addSubgroup( - new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT)); + new KeywordGroup("node", "author", "author2", true, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs)); GroupTreeNode node = parent.addSubgroup( - new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.INDEPENDENT)); + new KeywordGroup("node", "author", "author1", true, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs)); assertEquals(2, node.numberOfHits(entries)); } @Test public void setGroupChangesUnderlyingGroup() throws Exception { GroupTreeNode node = getNodeInSimpleTree(); - AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); node.setGroup(newGroup, true, entries); @@ -250,10 +263,10 @@ public void setGroupChangesUnderlyingGroup() throws Exception { @Test public void setGroupAddsPreviousAssignmentsExplicitToExplicit() throws Exception { - AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); - AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); node.setGroup(newGroup, true, entries); @@ -262,10 +275,10 @@ public void setGroupAddsPreviousAssignmentsExplicitToExplicit() throws Exception @Test public void setGroupWithFalseDoesNotAddsPreviousAssignments() throws Exception { - AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); - AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); node.setGroup(newGroup, false, entries); @@ -274,10 +287,10 @@ public void setGroupWithFalseDoesNotAddsPreviousAssignments() throws Exception { @Test public void setGroupAddsOnlyPreviousAssignments() throws Exception { - AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); assertFalse(oldGroup.isMatch(entry)); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); - AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); node.setGroup(newGroup, true, entries); @@ -286,7 +299,7 @@ public void setGroupAddsOnlyPreviousAssignments() throws Exception { @Test public void setGroupExplicitToSearchDoesNotKeepPreviousAssignments() throws Exception { - AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); AbstractGroup newGroup = new SearchGroup("NewGroup", "test", false, false, GroupHierarchyType.INDEPENDENT); @@ -298,10 +311,10 @@ public void setGroupExplicitToSearchDoesNotKeepPreviousAssignments() throws Exce @Test public void setGroupExplicitToExplicitIsRenameAndSoRemovesPreviousAssignment() throws Exception { - AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); - AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT); + AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT, Globals.prefs); node.setGroup(newGroup, true, entries); diff --git a/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java index 38166bfa7c01..8037c66cc4bc 100644 --- a/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/KeywordGroupTest.java @@ -1,5 +1,6 @@ package net.sf.jabref.logic.groups; +import net.sf.jabref.Globals; import net.sf.jabref.importer.fileformat.ParseException; import net.sf.jabref.model.entry.BibEntry; @@ -13,20 +14,21 @@ public class KeywordGroupTest { @Test public void testToString() throws ParseException { KeywordGroup group = new KeywordGroup("myExplicitGroup", "author","asdf", true, true, - GroupHierarchyType.INDEPENDENT); + GroupHierarchyType.INDEPENDENT, Globals.prefs); assertEquals("KeywordGroup:myExplicitGroup;0;author;asdf;1;1;", group.toString()); } @Test public void testToString2() throws ParseException { KeywordGroup group = new KeywordGroup("myExplicitGroup", "author","asdf", false, true, - GroupHierarchyType.REFINING); + GroupHierarchyType.REFINING, Globals.prefs); assertEquals("KeywordGroup:myExplicitGroup;1;author;asdf;0;1;", group.toString()); } @Test public void containsSimpleWord() throws Exception { - KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs); BibEntry entry = new BibEntry().withField("keywords", "test"); assertTrue(group.isMatch(entry)); @@ -34,7 +36,8 @@ public void containsSimpleWord() throws Exception { @Test public void containsSimpleWordInSentence() throws Exception { - KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs); BibEntry entry = new BibEntry().withField("keywords", "Some sentence containing test word"); assertTrue(group.isMatch(entry)); @@ -42,7 +45,8 @@ public void containsSimpleWordInSentence() throws Exception { @Test public void containsSimpleWordCommaSeparated() throws Exception { - KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs); BibEntry entry = new BibEntry().withField("keywords", "Some,list,containing,test,word"); assertTrue(group.isMatch(entry)); @@ -50,7 +54,8 @@ public void containsSimpleWordCommaSeparated() throws Exception { @Test public void containsSimpleWordSemicolonSeparated() throws Exception { - KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT); + KeywordGroup group = new KeywordGroup("name", "keywords", "test", false, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs); BibEntry entry = new BibEntry().withField("keywords", "Some;list;containing;test;word"); assertTrue(group.isMatch(entry)); @@ -58,7 +63,8 @@ public void containsSimpleWordSemicolonSeparated() throws Exception { @Test public void containsComplexWord() throws Exception { - KeywordGroup group = new KeywordGroup("name", "keywords", "\\H2O", false, false, GroupHierarchyType.INDEPENDENT); + KeywordGroup group = new KeywordGroup("name", "keywords", "\\H2O", false, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs); BibEntry entry = new BibEntry().withField("keywords", "\\H2O"); assertTrue(group.isMatch(entry)); @@ -66,7 +72,8 @@ public void containsComplexWord() throws Exception { @Test public void containsComplexWordInSentence() throws Exception { - KeywordGroup group = new KeywordGroup("name", "keywords", "\\H2O", false, false, GroupHierarchyType.INDEPENDENT); + KeywordGroup group = new KeywordGroup("name", "keywords", "\\H2O", false, false, GroupHierarchyType.INDEPENDENT, + Globals.prefs); BibEntry entry = new BibEntry().withField("keywords", "Some sentence containing \\H2O word"); assertTrue(group.isMatch(entry)); @@ -74,7 +81,8 @@ public void containsComplexWordInSentence() throws Exception { @Test public void containsWordWithWhitespaceInSentence() throws Exception { - KeywordGroup group = new KeywordGroup("name", "keywords", "test word", false, false, GroupHierarchyType.INDEPENDENT); + KeywordGroup group = new KeywordGroup("name", "keywords", "test word", false, false, + GroupHierarchyType.INDEPENDENT, Globals.prefs); BibEntry entry = new BibEntry().withField("keywords", "Some sentence containing test word"); assertTrue(group.isMatch(entry)); diff --git a/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java b/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java index 60d851edce7f..1521c48811f2 100644 --- a/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java +++ b/src/test/java/net/sf/jabref/logic/groups/SearchGroupTest.java @@ -27,7 +27,7 @@ public void testContains() { BibEntry entry = new BibEntry(); assertFalse(group.contains(entry)); - entry.addKeyword("review"); + entry.addKeyword("review", ", "); assertTrue(group.contains(entry)); } diff --git a/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java b/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java index b65d91872366..008d052afcbc 100644 --- a/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java +++ b/src/test/java/net/sf/jabref/logic/journals/AbbreviationsTest.java @@ -29,7 +29,8 @@ public void getNextAbbreviationAbbreviatesIEEEJournalTitle() { when(prefs.getBoolean(JabRefPreferences.USE_IEEE_ABRV)).thenReturn(true); assertEquals("#IEEE_J_PROC#", - abbreviations.getRepository().getNextAbbreviation("Proceedings of the IEEE").get()); + abbreviations.getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)) + .getNextAbbreviation("Proceedings of the IEEE").get()); } @Test @@ -37,24 +38,29 @@ public void getNextAbbreviationExpandsIEEEAbbreviation() { when(prefs.getBoolean(JabRefPreferences.USE_IEEE_ABRV)).thenReturn(true); assertEquals("Proceedings of the IEEE", - abbreviations.getRepository().getNextAbbreviation("#IEEE_J_PROC#").get()); + abbreviations.getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)) + .getNextAbbreviation("#IEEE_J_PROC#").get()); } @Test public void getNextAbbreviationAbbreviatesJournalTitle() { assertEquals("Proc. IEEE", - abbreviations.getRepository().getNextAbbreviation("Proceedings of the IEEE").get()); + abbreviations.getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)) + .getNextAbbreviation("Proceedings of the IEEE").get()); } @Test public void getNextAbbreviationRemovesPoint() { - assertEquals("Proc IEEE", abbreviations.getRepository().getNextAbbreviation("Proc. IEEE").get()); + assertEquals("Proc IEEE", + abbreviations.getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)) + .getNextAbbreviation("Proc. IEEE").get()); } @Test public void getNextAbbreviationExpandsAbbreviation() { assertEquals("Proceedings of the IEEE", - abbreviations.getRepository().getNextAbbreviation("Proc IEEE").get()); + abbreviations.getRepository(JournalAbbreviationPreferences.fromPreferences(Globals.prefs)) + .getNextAbbreviation("Proc IEEE").get()); } } diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java index bbf289d027bc..467bbf64ecd8 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java @@ -86,7 +86,7 @@ public void setUp() { public String layout(String layoutFile, BibEntry entry, Optional highlightPattern) throws IOException { StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); - Layout layout = new LayoutHelper(sr, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); + Layout layout = new LayoutHelper(sr, Globals.prefs, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); return layout.doLayout(entry, null, highlightPattern); } diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java index a25aa6797350..e045a7eff4dc 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java @@ -53,7 +53,7 @@ public String layout(String layoutFile, String entry) throws IOException { BibEntry be = LayoutTest.bibtexString2BibtexEntry(entry); StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); - Layout layout = new LayoutHelper(sr, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); + Layout layout = new LayoutHelper(sr, Globals.prefs, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); return layout.doLayout(be, null); } diff --git a/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java b/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java index 3c78f9c424c3..df66e221d17d 100644 --- a/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java @@ -21,40 +21,40 @@ public void setUp() throws Exception { @Test public void testEmpty() { - assertEquals("", new FileLink().format("")); + assertEquals("", new FileLink(Globals.prefs).format("")); } @Test public void testNull() { - assertEquals("", new FileLink().format(null)); + assertEquals("", new FileLink(Globals.prefs).format(null)); } @Test public void testOnlyFilename() { - assertEquals("test.pdf", new FileLink().format("test.pdf")); + assertEquals("test.pdf", new FileLink(Globals.prefs).format("test.pdf")); } @Test public void testCompleteRecord() { - assertEquals("test.pdf", new FileLink().format("paper:test.pdf:PDF")); + assertEquals("test.pdf", new FileLink(Globals.prefs).format("paper:test.pdf:PDF")); } @Test public void testMultipleFiles() { - ParamLayoutFormatter a = new FileLink(); + ParamLayoutFormatter a = new FileLink(Globals.prefs); assertEquals("test.pdf", a.format("paper:test.pdf:PDF;presentation:pres.ppt:PPT")); } @Test public void testMultipleFilesPick() { - ParamLayoutFormatter a = new FileLink(); + ParamLayoutFormatter a = new FileLink(Globals.prefs); a.setArgument("ppt"); assertEquals("pres.ppt", a.format("paper:test.pdf:PDF;presentation:pres.ppt:PPT")); } @Test public void testMultipleFilesPickNonExistant() { - ParamLayoutFormatter a = new FileLink(); + ParamLayoutFormatter a = new FileLink(Globals.prefs); a.setArgument("doc"); assertEquals("", a.format("paper:test.pdf:PDF;presentation:pres.ppt:PPT")); } diff --git a/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java b/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java index ffee836e282d..1fbde9a3c619 100644 --- a/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java +++ b/src/test/java/net/sf/jabref/logic/net/URLDownloadTest.java @@ -27,7 +27,8 @@ public void testStringDownload() throws IOException { try { URLDownload dl = new URLDownload(new URL("http://www.google.com")); - Assert.assertTrue("google.com should contain google", dl.downloadToString().contains("Google")); + Assert.assertTrue("google.com should contain google", + dl.downloadToString(Globals.prefs.getDefaultEncoding()).contains("Google")); } finally { Globals.prefs = null; } diff --git a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java index 65fa1cf5b069..5e39f3981ea9 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java @@ -49,7 +49,7 @@ public void tearDown() { @Test public void testAuthorYear() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertTrue(style.isValid()); assertTrue(style.isFromResource()); @@ -67,7 +67,7 @@ public void testAuthorYearAsFile() throws URISyntaxException, IOException { File defFile = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile(); - OOBibStyle style = new OOBibStyle(defFile, mock(JournalAbbreviationLoader.class), + OOBibStyle style = new OOBibStyle(defFile, Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertTrue(style.isValid()); assertFalse(style.isFromResource()); @@ -82,7 +82,7 @@ public void testAuthorYearAsFile() throws URISyntaxException, IOException { @Test public void testNumerical() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertTrue(style.isValid()); assertFalse(style.isBibtexKeyCiteMarkers()); @@ -96,7 +96,7 @@ public void testNumerical() throws IOException { @Test public void testGetNumCitationMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertEquals("[1] ", style.getNumCitationMarker(Arrays.asList(1), -1, true)); assertEquals("[1]", style.getNumCitationMarker(Arrays.asList(1), -1, false)); @@ -113,7 +113,7 @@ public void testGetNumCitationMarker() throws IOException { @Test public void testGetNumCitationMarkerUndefined() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "; 2-4] ", style.getNumCitationMarker(Arrays.asList(4, 2, 3, 0), 1, true)); @@ -131,7 +131,7 @@ public void testGetNumCitationMarkerUndefined() throws IOException { @Test public void testGetCitProperty() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertEquals(", ", style.getStringCitProperty("AuthorSeparator")); assertEquals(3, style.getIntCitProperty("MaxAuthors")); @@ -146,7 +146,7 @@ public void testGetCitProperty() throws IOException { public void testGetCitationMarker() throws IOException { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); BibDatabase db = result.getDatabase(); @@ -167,7 +167,7 @@ public void testGetCitationMarker() throws IOException { public void testLayout() throws IOException { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); BibDatabase db = result.getDatabase(); @@ -187,7 +187,7 @@ public void testLayout() throws IOException { @Test public void testInstitutionAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); BibDatabase database = new BibDatabase(); @@ -206,7 +206,7 @@ public void testInstitutionAuthor() throws IOException { @Test public void testVonAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); BibDatabase database = new BibDatabase(); @@ -225,7 +225,7 @@ public void testVonAuthor() throws IOException { @Test public void testInstitutionAuthorMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -245,7 +245,7 @@ public void testInstitutionAuthorMarker() throws IOException { @Test public void testVonAuthorMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -265,7 +265,7 @@ public void testVonAuthorMarker() throws IOException { @Test public void testNullAuthorMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -283,7 +283,7 @@ public void testNullAuthorMarker() throws IOException { @Test public void testNullYearMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -301,7 +301,7 @@ public void testNullYearMarker() throws IOException { @Test public void testEmptyEntryMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -318,7 +318,7 @@ public void testEmptyEntryMarker() throws IOException { @Test public void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -354,7 +354,7 @@ public void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { @Test public void testGetCitationMarkerInTextUniquefiers() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -390,7 +390,7 @@ public void testGetCitationMarkerInTextUniquefiers() throws IOException { @Test public void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -425,7 +425,7 @@ public void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throw @Test public void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); @@ -461,9 +461,9 @@ public void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOExc @Test // TODO: equals only work when initialized from file, not from reader public void testEquals() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertEquals(style1, style2); } @@ -471,27 +471,27 @@ public void testEquals() throws IOException { @Test // TODO: equals only work when initialized from file, not from reader public void testNotEquals() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertNotEquals(style1, style2); } @Test public void testCompareToEqual() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertEquals(0, style1.compareTo(style2)); } @Test public void testCompareToNotEqual() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, Globals.prefs, mock(JournalAbbreviationLoader.class)); assertTrue(style1.compareTo(style2) > 0); assertFalse(style2.compareTo(style1) > 0); @@ -501,7 +501,7 @@ public void testCompareToNotEqual() throws IOException { @Ignore public void testEmptyStringPropertyAndOxfordComma() throws URISyntaxException, IOException { String fileName = Paths.get(OOBibStyleTest.class.getResource("test.jstyle").toURI()).toString(); - OOBibStyle style = new OOBibStyle(fileName, mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(fileName, Globals.prefs, mock(JournalAbbreviationLoader.class)); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); BibDatabase database = new BibDatabase(); diff --git a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java index d86bd968523a..7aa754418396 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java @@ -48,21 +48,21 @@ public void tearDown() throws Exception { @Test(expected = NullPointerException.class) public void throwNPEWithNullPreferences() { - loader = new StyleLoader(null, + loader = new StyleLoader(null, Globals.prefs, mock(JournalAbbreviationLoader.class), mock(Charset.class)); fail(); } @Test(expected = NullPointerException.class) public void throwNPEWithNullRepository() { - loader = new StyleLoader(mock(OpenOfficePreferences.class), + loader = new StyleLoader(mock(OpenOfficePreferences.class), Globals.prefs, null, mock(Charset.class)); fail(); } @Test(expected = NullPointerException.class) public void throwNPEWithNullCharset() { - loader = new StyleLoader(mock(OpenOfficePreferences.class), + loader = new StyleLoader(mock(OpenOfficePreferences.class), Globals.prefs, mock(JournalAbbreviationLoader.class), null); fail(); } @@ -70,7 +70,7 @@ public void throwNPEWithNullCharset() { @Test public void testGetStylesWithEmptyExternal() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, + loader = new StyleLoader(preferences, Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertEquals(2, loader.getStyles().size()); @@ -79,7 +79,7 @@ public void testGetStylesWithEmptyExternal() { @Test public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, + loader = new StyleLoader(preferences, Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) @@ -92,7 +92,7 @@ public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { public void testAddInvalidStyleLeadsToNoMoreStyle() { preferences.setExternalStyles(Collections.emptyList()); Globals.prefs.putStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES, Collections.emptyList()); - loader = new StyleLoader(preferences, + loader = new StyleLoader(preferences, Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); int beforeAdding = loader.getStyles().size(); loader.addStyleIfValid("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky"); @@ -104,7 +104,7 @@ public void testInitalizeWithOneExternalFile() throws URISyntaxException { String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); preferences.setExternalStyles(Collections.singletonList(filename)); - loader = new StyleLoader(preferences, + loader = new StyleLoader(preferences, Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertEquals(numberOfInternalStyles + 1, loader.getStyles().size()); } @@ -113,7 +113,7 @@ public void testInitalizeWithOneExternalFile() throws URISyntaxException { public void testInitalizeWithIncorrectExternalFile() { preferences.setExternalStyles(Collections.singletonList("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky")); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); assertEquals(numberOfInternalStyles, loader.getStyles().size()); } @@ -124,7 +124,7 @@ public void testInitalizeWithOneExternalFileRemoveStyle() throws URISyntaxExcept .toFile().getPath(); preferences.setExternalStyles(Collections.singletonList(filename)); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); int beforeRemoving = loader.getStyles().size(); @@ -146,7 +146,7 @@ public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() thro .toFile().getPath(); preferences.setExternalStyles(Collections.singletonList(filename)); - loader = new StyleLoader(preferences, + loader = new StyleLoader(preferences, Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { @@ -164,7 +164,7 @@ public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() thro @Test public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); int beforeAdding = loader.getStyles().size(); String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) @@ -176,7 +176,7 @@ public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException @Test(expected = NullPointerException.class) public void testAddNullStyleThrowsNPE() { - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); loader.addStyleIfValid(null); fail(); @@ -186,7 +186,7 @@ public void testAddNullStyleThrowsNPE() { @Test public void testGetDefaultUsedStyleWhenEmpty() { Globals.prefs.remove(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); @@ -197,7 +197,7 @@ public void testGetDefaultUsedStyleWhenEmpty() { @Test public void testGetStoredUsedStyle() { preferences.setCurrentStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); @@ -208,7 +208,7 @@ public void testGetStoredUsedStyle() { @Test public void testGtDefaultUsedStyleWhenIncorrect() { preferences.setCurrentStyle("ljlkjlkjnljnvdlsjniuhwelfhuewfhlkuewhfuwhelu"); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); @@ -220,7 +220,7 @@ public void testGtDefaultUsedStyleWhenIncorrect() { public void testRemoveInternalStyleReturnsFalseAndDoNotRemove() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, mock(JournalAbbreviationLoader.class), + loader = new StyleLoader(preferences, Globals.prefs, mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { diff --git a/src/test/java/net/sf/jabref/logic/search/SearchQueryTest.java b/src/test/java/net/sf/jabref/logic/search/SearchQueryTest.java index d338a81d0789..930b22697f42 100644 --- a/src/test/java/net/sf/jabref/logic/search/SearchQueryTest.java +++ b/src/test/java/net/sf/jabref/logic/search/SearchQueryTest.java @@ -33,7 +33,7 @@ public void testIsGrammarBasedSearch() { @Test public void testGrammarSearch() { BibEntry entry = new BibEntry(); - entry.addKeyword("one two"); + entry.addKeyword("one two", ", "); SearchQuery searchQuery = new SearchQuery("keywords=\"one two\"", false, false); assertTrue(searchQuery.isMatch(entry)); } diff --git a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java index b778f48a1d7b..c4af6d4784d9 100644 --- a/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/util/io/FileUtilTest.java @@ -40,7 +40,8 @@ public void testGetLinkedFileNameDefault() { entry.setCiteKey("1234"); entry.setField("title", "mytitle"); - assertEquals("1234 - mytitle", FileUtil.createFileNameFromPattern(null, entry, mock(JournalAbbreviationLoader.class))); + assertEquals("1234 - mytitle", + FileUtil.createFileNameFromPattern(null, entry, mock(JournalAbbreviationLoader.class), Globals.prefs)); } @Test @@ -52,7 +53,8 @@ public void testGetLinkedFileNameBibTeXKey() { entry.setCiteKey("1234"); entry.setField("title", "mytitle"); - assertEquals("1234", FileUtil.createFileNameFromPattern(null, entry, mock(JournalAbbreviationLoader.class))); + assertEquals("1234", + FileUtil.createFileNameFromPattern(null, entry, mock(JournalAbbreviationLoader.class), Globals.prefs)); } @Test @@ -128,5 +130,5 @@ public void uniquePathSubstrings() { assertEquals(uniqPath, result); } - + } diff --git a/src/test/java/net/sf/jabref/logic/util/io/UtilFindFileTest.java b/src/test/java/net/sf/jabref/logic/util/io/UtilFindFileTest.java index 56c38425ee22..b383ed53a5a4 100644 --- a/src/test/java/net/sf/jabref/logic/util/io/UtilFindFileTest.java +++ b/src/test/java/net/sf/jabref/logic/util/io/UtilFindFileTest.java @@ -8,6 +8,7 @@ import java.util.Map; import net.sf.jabref.FileBasedTestCase; +import net.sf.jabref.Globals; import net.sf.jabref.model.entry.BibEntry; import org.junit.Assert; @@ -30,7 +31,7 @@ public void testFindAssociatedFiles() { Collection dirs = Arrays.asList(new File(root.getAbsoluteFile() + "/pdfs/"), new File(root.getAbsoluteFile() + "/graphicsDir/")); - Map> results = FileUtil.findAssociatedFiles(entries, extensions, dirs); + Map> results = FileUtil.findAssociatedFiles(entries, extensions, dirs, Globals.prefs); Assert.assertEquals(2, results.get(entry).size()); Assert.assertTrue( diff --git a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java index de3bd4184749..11864d22c69c 100644 --- a/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java +++ b/src/test/java/net/sf/jabref/logic/xmp/XMPUtilTest.java @@ -31,6 +31,7 @@ import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; +import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; @@ -141,7 +142,8 @@ public static BibEntry bibtexString2BibtexEntry(String s) throws IOException { public static String bibtexEntry2BibtexString(BibEntry e) throws IOException { StringWriter sw = new StringWriter(); - new BibEntryWriter(new LatexFieldFormatter(), false).write(e, sw, BibDatabaseMode.BIBTEX); + new BibEntryWriter(new LatexFieldFormatter(LatexFieldFormatterPreferences.fromPreferences(Globals.prefs)), + false).write(e, sw, BibDatabaseMode.BIBTEX); return sw.getBuffer().toString(); } @@ -267,7 +269,7 @@ public void testReadXMPSimple() throws COSVisitorException, IOException { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(XMPUtilTest.bibtexDescription(bibtex))); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -292,7 +294,7 @@ public void testReadXMPUTF8() throws COSVisitorException, IOException { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(XMPUtilTest.bibtexDescription(bibtex))); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -320,7 +322,7 @@ public void testPrivacyFilter() throws IOException, TransformerException { XMPUtil.writeXMP(pdfFile, e, null); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry x = l.get(0); @@ -338,7 +340,7 @@ public void testPrivacyFilter() throws IOException, TransformerException { XMPUtil.writeXMP(pdfFile, e, null); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry x = l.get(0); Set ts = x.getFieldNames(); @@ -366,7 +368,7 @@ public void testReadXMPSeq() throws COSVisitorException, IOException { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(XMPUtilTest.bibtexDescription(bibtex))); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -390,7 +392,7 @@ public void testReadXMPEntryType() throws COSVisitorException, IOException { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(XMPUtilTest.bibtexDescription(bibtex))); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -465,7 +467,7 @@ public void testReadWriteXMP() throws IOException, TransformerException { XMPUtil.writeXMP(pdfFile, e, null); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry x = l.get(0); @@ -487,7 +489,7 @@ public void testNewlineHandling() throws COSVisitorException, IOException { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(XMPUtilTest.bibtexDescription(bibtex))); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -511,7 +513,7 @@ public void testAttributeRead() throws COSVisitorException, IOException { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(bibtex)); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -521,7 +523,7 @@ public void testAttributeRead() throws COSVisitorException, IOException { @Test public void testEmpty() throws Exception { - Assert.assertEquals(Collections.emptyList(), XMPUtil.readXMP(pdfFile)); + Assert.assertEquals(Collections.emptyList(), XMPUtil.readXMP(pdfFile, Globals.prefs)); } @@ -549,7 +551,7 @@ public void testSimpleUpdate() throws Exception { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(s)); // Nothing there yet, but should not crash - Assert.assertEquals(Collections.emptyList(), XMPUtil.readXMP(pdfFile)); + Assert.assertEquals(Collections.emptyList(), XMPUtil.readXMP(pdfFile, Globals.prefs)); s = " " + " Acrobat PDFMaker 7.0.7" @@ -569,13 +571,13 @@ public void testSimpleUpdate() throws Exception { // Title is Questionnaire.pdf so the DublinCore fallback should hit // in... - Assert.assertEquals(1, XMPUtil.readXMP(pdfFile).size()); + Assert.assertEquals(1, XMPUtil.readXMP(pdfFile, Globals.prefs).size()); { // Now write new packet and check if it was correctly written XMPUtil.writeXMP(pdfFile, t1BibtexEntry(), null); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -651,7 +653,7 @@ public void testSimpleUpdate() throws Exception { XMPUtil.writeXMP(pdfFile, toSet, null); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry e = l.get(0); @@ -742,7 +744,7 @@ public void testXMLEscape() throws Exception { XMPUtil.writeXMP(pdfFile, e, null); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry x = l.get(0); @@ -802,7 +804,7 @@ public void testXMPreadString() throws Exception { /* Test contents of string */ writeManually(pdfFile, xmp); - List l = XMPUtil.readXMP(pdfFile); + List l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(2, l.size()); @@ -837,7 +839,7 @@ public void testReadMultiple() throws Exception { writeManually(pdfFile, XMPUtilTest.bibtexXPacket(bibtex)); // Read from file - List l = XMPUtil.readXMP(pdfFile); + List l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(2, l.size()); @@ -868,7 +870,7 @@ public void testWriteMultiple() throws IOException, TransformerException { XMPUtil.writeXMP(pdfFile, l, null, false); - l = XMPUtil.readXMP(pdfFile); + l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(2, l.size()); @@ -891,7 +893,7 @@ public void testWriteMultiple() throws IOException, TransformerException { @Test public void testReadProtectedPDFHasMetaData() throws Exception { try (InputStream is = XMPUtilTest.class.getResourceAsStream("/pdfs/write-protected.pdf")) { - Assert.assertTrue(XMPUtil.hasMetadata(is)); + Assert.assertTrue(XMPUtil.hasMetadata(is, Globals.prefs)); } } @@ -901,7 +903,7 @@ public void testReadProtectedPDFHasMetaData() throws Exception { @Test public void testReadProtectedPDFHasCorrectMetaData() throws Exception { try (InputStream is = XMPUtilTest.class.getResourceAsStream("/pdfs/write-protected.pdf")) { - List readEntries = XMPUtil.readXMP(is); + List readEntries = XMPUtil.readXMP(is, Globals.prefs); BibEntry entry = new BibEntry(); entry.setType("misc"); @@ -971,7 +973,8 @@ public void testReadWriteDC() throws IOException, TransformerException { */ Assert.assertEquals(4, dcSchema.getRelationships().size()); - assertEqualsBibtexEntry(t3BibtexEntry(), XMPUtil.getBibtexEntryFromDublinCore(dcSchema).get()); + assertEqualsBibtexEntry(t3BibtexEntry(), + XMPUtil.getBibtexEntryFromDublinCore(dcSchema, Globals.prefs).get()); } @@ -1036,7 +1039,8 @@ public void testWriteSingleUpdatesDCAndInfo() throws IOException, TransformerExc */ Assert.assertEquals(4, dcSchema.getRelationships().size()); - assertEqualsBibtexEntry(t3BibtexEntry(), XMPUtil.getBibtexEntryFromDublinCore(dcSchema).get()); + assertEqualsBibtexEntry(t3BibtexEntry(), + XMPUtil.getBibtexEntryFromDublinCore(dcSchema, Globals.prefs).get()); } } @@ -1112,7 +1116,7 @@ public void testCommandLineSingleBib() throws IOException, TransformerException, writeManually(pdfFile, xmp); } - List l = XMPUtil.readXMP(pdfFile); + List l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(1, l.size()); assertEqualsBibtexEntry(t1BibtexEntry(), l.get(0)); @@ -1181,7 +1185,7 @@ public void testCommandLineSinglePdf() throws IOException, TransformerException, /* Test contents of string */ writeManually(pdfFile, xmp); - List l = XMPUtil.readXMP(pdfFile); + List l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(1, l.size()); assertEqualsBibtexEntry(t1BibtexEntry(), l.get(0)); @@ -1213,7 +1217,7 @@ public void testCommandLineByKey() throws IOException, TransformerException { } // PDF should be annotated: - List l = XMPUtil.readXMP(pdfFile); + List l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(1, l.size()); assertEqualsBibtexEntry(t1BibtexEntry(), l.get(0)); } @@ -1229,7 +1233,7 @@ public void testCommandLineByKey() throws IOException, TransformerException { } // PDF should be annotated: - List l = XMPUtil.readXMP(pdfFile); + List l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(1, l.size()); assertEqualsBibtexEntry(t2BibtexEntry(), l.get(0)); } finally { @@ -1262,7 +1266,7 @@ public void testCommandLineSeveral() throws IOException, TransformerException { XMPUtil.main(new String[] {tempBib.getAbsolutePath(), pdfFile.getAbsolutePath()}); System.setOut(oldOut); } - List l = XMPUtil.readXMP(pdfFile); + List l = XMPUtil.readXMP(pdfFile, Globals.prefs); Assert.assertEquals(2, l.size()); @@ -1316,7 +1320,7 @@ public void testResolveStrings() throws IOException, TransformerException { XMPUtil.writeXMP(pdfFile, e, original.getDatabase()); - List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile()); + List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile(), Globals.prefs); Assert.assertEquals(1, l.size()); BibEntry x = l.get(0); @@ -1327,7 +1331,7 @@ public void testResolveStrings() throws IOException, TransformerException { @Test(expected = EncryptedPdfsNotSupportedException.class) public void expectedEncryptionNotSupportedExceptionAtRead() throws IOException { try (InputStream is = XMPUtilTest.class.getResourceAsStream("/pdfs/encrypted.pdf")) { - XMPUtil.readXMP(is); + XMPUtil.readXMP(is, Globals.prefs); } } @@ -1361,7 +1365,7 @@ public void testResolveStrings2() throws IOException, TransformerException { result.getDatabase()); // Test whether we the main function can load the bibtex correctly - BibEntry b = XMPUtil.readXMP(pdfFile).get(0); + BibEntry b = XMPUtil.readXMP(pdfFile, Globals.prefs).get(0); Assert.assertNotNull(b); Assert.assertEquals(originalAuthors, AuthorList.parse(b.getFieldOptional("author").get())); @@ -1396,7 +1400,7 @@ public void testResolveStrings2() throws IOException, TransformerException { Assert.assertEquals("Arvind", dcSchema.getCreators().get(1)); Assert.assertEquals("Krste Asanov\\'\\i{}c", dcSchema.getCreators().get(2)); - b = XMPUtil.getBibtexEntryFromDublinCore(dcSchema).get(); + b = XMPUtil.getBibtexEntryFromDublinCore(dcSchema, Globals.prefs).get(); Assert.assertNotNull(b); Assert.assertEquals(originalAuthors, AuthorList.parse(b.getFieldOptional("author").get())); } diff --git a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java index 0d2c76710283..0d0d40cfa799 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibEntryTests.java @@ -212,16 +212,21 @@ public void setNullField() { @Test(expected = NullPointerException.class) public void addNullKeywordThrowsNPE() { - keywordEntry.addKeyword(null); + keywordEntry.addKeyword(null, ", "); Assert.fail(); } @Test(expected = NullPointerException.class) public void putNullKeywordListThrowsNPE() { - keywordEntry.putKeywords(null); + keywordEntry.putKeywords(null, ", "); Assert.fail(); } + @Test(expected = NullPointerException.class) + public void putNullKeywordSeparatorThrowsNPE() { + keywordEntry.putKeywords(Arrays.asList("A", "B"), null); + Assert.fail(); + } @Test public void testGetSeparatedKeywordsAreCorrect() { String[] expected = {"Foo", "Bar"}; @@ -230,48 +235,48 @@ public void testGetSeparatedKeywordsAreCorrect() { @Test public void testAddKeywordIsCorrect() { - keywordEntry.addKeyword("FooBar"); + keywordEntry.addKeyword("FooBar", ", "); String[] expected = {"Foo", "Bar", "FooBar"}; Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test public void testAddKeywordHasChanged() { - keywordEntry.addKeyword("FooBar"); + keywordEntry.addKeyword("FooBar", ", "); Assert.assertTrue(keywordEntry.hasChanged()); } @Test public void testAddKeywordTwiceYiedsOnlyOne() { - keywordEntry.addKeyword("FooBar"); - keywordEntry.addKeyword("FooBar"); + keywordEntry.addKeyword("FooBar", ", "); + keywordEntry.addKeyword("FooBar", ", "); String[] expected = {"Foo", "Bar", "FooBar"}; Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test public void addKeywordIsCaseSensitive() { - keywordEntry.addKeyword("FOO"); + keywordEntry.addKeyword("FOO", ", "); String[] expected = {"Foo", "Bar", "FOO"}; Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test public void testAddKeywordWithDifferentCapitalizationChanges() { - keywordEntry.addKeyword("FOO"); + keywordEntry.addKeyword("FOO", ", "); Assert.assertTrue(keywordEntry.hasChanged()); } @Test public void testAddKeywordEmptyKeywordIsNotAdded() { - keywordEntry.addKeyword(""); + keywordEntry.addKeyword("", ", "); String[] expected = {"Foo", "Bar"}; Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test public void testAddKeywordEmptyKeywordNotChanged() { - keywordEntry.addKeyword(""); + keywordEntry.addKeyword("", ", "); Assert.assertFalse(keywordEntry.hasChanged()); } @@ -282,81 +287,85 @@ public void texNewBibEntryHasNoKeywords() { @Test public void texNewBibEntryHasNoKeywordsEvenAfterAddingEmptyKeyword() { - emptyEntry.addKeyword(""); + emptyEntry.addKeyword("", ", "); Assert.assertTrue(emptyEntry.getKeywords().isEmpty()); } @Test public void texNewBibEntryAfterAddingEmptyKeywordNotChanged() { - emptyEntry.addKeyword(""); + emptyEntry.addKeyword("", ", "); Assert.assertFalse(emptyEntry.hasChanged()); } @Test public void testAddKeywordsWorksAsExpected() { String[] expected = {"Foo", "Bar"}; - emptyEntry.addKeywords(keywordEntry.getKeywords()); + emptyEntry.addKeywords(keywordEntry.getKeywords(), ", "); Assert.assertArrayEquals(expected, emptyEntry.getKeywords().toArray()); } @Test public void testPutKeywordsOverwritesOldKeywords() { - keywordEntry.putKeywords(Arrays.asList("Yin", "Yang")); + keywordEntry.putKeywords(Arrays.asList("Yin", "Yang"), ", "); String[] expected = {"Yin", "Yang"}; Assert.assertArrayEquals(expected, keywordEntry.getKeywords().toArray()); } @Test public void testPutKeywordsHasChanged() { - keywordEntry.putKeywords(Arrays.asList("Yin", "Yang")); + keywordEntry.putKeywords(Arrays.asList("Yin", "Yang"), ", "); Assert.assertTrue(keywordEntry.hasChanged()); } @Test public void testPutKeywordsPutEmpyListErasesPreviousKeywords() { - keywordEntry.putKeywords(Collections.emptyList()); + keywordEntry.putKeywords(Collections.emptyList(), ", "); Assert.assertTrue(keywordEntry.getKeywords().isEmpty()); } @Test public void testPutKeywordsPutEmpyListHasChanged() { - keywordEntry.putKeywords(Collections.emptyList()); + keywordEntry.putKeywords(Collections.emptyList(), ", "); Assert.assertTrue(keywordEntry.hasChanged()); } @Test public void testPutKeywordsPutEmpyListToEmptyBibentry() { - emptyEntry.putKeywords(Collections.emptyList()); + emptyEntry.putKeywords(Collections.emptyList(), ", "); Assert.assertTrue(emptyEntry.getKeywords().isEmpty()); } @Test public void testPutKeywordsPutEmpyListToEmptyBibentryNotChanged() { - emptyEntry.putKeywords(Collections.emptyList()); + emptyEntry.putKeywords(Collections.emptyList(), ", "); Assert.assertFalse(emptyEntry.hasChanged()); } @Test public void putKeywordsToEmptyReturnsNoChange() { - Optional change = emptyEntry.putKeywords(Collections.emptyList()); + Optional change = emptyEntry.putKeywords(Collections.emptyList(), + ", "); Assert.assertEquals(Optional.empty(), change); } @Test public void clearKeywordsReturnsChange() { - Optional change = keywordEntry.putKeywords(Collections.emptyList()); + Optional change = keywordEntry.putKeywords(Collections.emptyList(), + ", "); Assert.assertEquals(Optional.of(new FieldChange(keywordEntry, "keywords", "Foo, Bar", null)), change); } @Test public void changeKeywordsReturnsChange() { - Optional change = keywordEntry.putKeywords(Arrays.asList("Test", "FooTest")); + Optional change = keywordEntry.putKeywords(Arrays.asList("Test", "FooTest"), + ", "); Assert.assertEquals(Optional.of(new FieldChange(keywordEntry, "keywords", "Foo, Bar", "Test, FooTest")), change); } @Test public void putKeywordsToSameReturnsNoChange() { - Optional change = keywordEntry.putKeywords(Arrays.asList("Foo", "Bar")); + Optional change = keywordEntry.putKeywords(Arrays.asList("Foo", "Bar"), + ", "); Assert.assertEquals(Optional.empty(), change); } diff --git a/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java b/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java index cd451c2c52b7..b014caf2c426 100644 --- a/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java +++ b/src/test/java/net/sf/jabref/sql/DatabaseImportExportTests.java @@ -179,7 +179,8 @@ private BibDatabaseContext createContextWithSingleEntrySingleGroup() throws Pars BibDatabaseContext databaseContext = createContextWithSingleEntry(); GroupTreeNode root = GroupTreeNode.fromGroup(new AllEntriesGroup()); - KeywordGroup group = new KeywordGroup("test", "asdf", "fdas", false, true, GroupHierarchyType.INCLUDING); + KeywordGroup group = new KeywordGroup("test", "asdf", "fdas", false, true, GroupHierarchyType.INCLUDING, + Globals.prefs); root.addSubgroup(group); databaseContext.getMetaData().setGroups(root); return databaseContext; From 6fb9251199e5004c2450d61bc67cd4b435752f5d Mon Sep 17 00:00:00 2001 From: tschechlovdev Date: Thu, 21 Jul 2016 12:49:16 +0200 Subject: [PATCH 253/268] Rewrite MedlineImporter with JAXB and add nbib fields (#1479) --- CHANGELOG.md | 2 +- build.gradle | 1 + medline.gradle | 18 + .../importer/fileformat/MedlineHandler.java | 547 ----------- .../importer/fileformat/MedlineImporter.java | 629 ++++++++++++- .../resources/xjc/medline/bookdoc_160101.xsd | 261 ++++++ src/main/resources/xjc/medline/medline.xsd | 314 +++++++ .../medline/nlmmedlinecitationset_160101.xsd | 861 ++++++++++++++++++ .../fileformat/MedlineImporterTest.java | 7 - .../fileformat/MedlineImporterTestFiles.java | 5 +- .../MedlineImporterTestArticleID.bib | 25 +- .../MedlineImporterTestArticleID.xml | 7 +- .../MedlineImporterTestBookArticleSet.bib | 20 + .../MedlineImporterTestBookArticleSet.xml | 80 ++ .../MedlineImporterTestKeywordSingleEntry.bib | 25 + .../MedlineImporterTestKeywordSingleEntry.xml | 88 ++ .../fileformat/MedlineImporterTestNbib.bib | 51 ++ .../fileformat/MedlineImporterTestNbib.xml | 372 ++++++++ .../MedlineImporterTestPubmedBook.bib | 15 + .../MedlineImporterTestPubmedBook.xml | 143 +++ .../MedlineImporterTestSingleEntry.bib | 15 - .../MedlineImporterTestSingleEntry.xml | 143 --- 22 files changed, 2855 insertions(+), 774 deletions(-) create mode 100644 medline.gradle delete mode 100644 src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java create mode 100644 src/main/resources/xjc/medline/bookdoc_160101.xsd create mode 100644 src/main/resources/xjc/medline/medline.xsd create mode 100644 src/main/resources/xjc/medline/nlmmedlinecitationset_160101.xsd create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.xml delete mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib delete mode 100644 src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e81b4856701..18e7e7016d7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -128,7 +128,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Integrity check table can be sorted by clicking on column headings - Added \SOFTWARE\Jabref 'Path' registry entry for installation path inside the installer - Added an additional icon to distinguish DOI and URL links ([feature request #696](https://github.com/JabRef/jabref/issues/696)) -- Added nbib fields to Medlineplain importer +- Added nbib fields to Medlineplain importer and to MedlineImporter - Implemented [#1342](https://github.com/JabRef/jabref/issues/1342): show description of case converters as tooltip - Updated German translation diff --git a/build.gradle b/build.gradle index 7bad1052dde2..6540c9b50295 100644 --- a/build.gradle +++ b/build.gradle @@ -38,6 +38,7 @@ apply plugin: 'checkstyle' apply from: 'eclipse.gradle' apply from: 'localization.gradle' +apply from: 'medline.gradle' group = "net.sf.jabref" version = "3.6dev" diff --git a/medline.gradle b/medline.gradle new file mode 100644 index 000000000000..6fbce0615c82 --- /dev/null +++ b/medline.gradle @@ -0,0 +1,18 @@ + +configurations { + xjc +} + +dependencies { + xjc group: 'com.sun.xml.bind', name: 'jaxb-xjc', version: '2.2.4-1' +} + +task xjc () << { + ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.xjc.asPath) + + ant.xjc(destdir: 'src/main/gen/', package: 'net.sf.jabref.importer.fileformat.medline'){ + schema(dir: 'src/main/resources/xjc/medline', includes: 'medline.xsd') + } +} + +tasks. compileJava.dependsOn xjc diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java deleted file mode 100644 index d9bf5a553ee9..000000000000 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineHandler.java +++ /dev/null @@ -1,547 +0,0 @@ -/* Copyright (C) 2003-2016 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.importer.fileformat; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import net.sf.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.IdGenerator; - -import org.xml.sax.Attributes; -import org.xml.sax.helpers.DefaultHandler; - -class MedlineHandler extends DefaultHandler { - - private static final UnicodeToLatexFormatter UNICODE_CONVERTER = new UnicodeToLatexFormatter(); - private final List bibitems = new ArrayList<>(); - private boolean inTitle; - private boolean inYear; - private boolean inJournal; - private boolean inMonth; - private boolean inVolume; - private boolean inAuthorList; - private boolean inAuthor; - private boolean inLastName; - private boolean inSuffix; - private boolean inInitials; - private boolean inMedlinePgn; - private boolean inIssue; - private boolean inPubDate; - private boolean inUrl; - private boolean inForename; - private boolean inAbstractText; - private boolean inMedlineDate; - private boolean inPubMedID; - private boolean inDescriptorName; - private boolean inDoi; - private boolean inPii; - private boolean inPmc; - private boolean inAffiliation; - private boolean inMeshHeader; - private boolean inQualifierName; - private boolean inLanguage; - private boolean inPst; - private String title = ""; - private String journal = ""; - private String author = ""; - private String lastName = ""; - private String suffix = ""; - private String year = ""; - private String forename = ""; - private String abstractText = ""; - private String affiliation = ""; - private String month = ""; - private String volume = ""; - private String lastname = ""; - private String initials = ""; - private String number = ""; - private String page = ""; - private String medlineDate = ""; - private final String series = ""; - private final String editor = ""; - private final String booktitle = ""; - private final String type = "article"; - private final String key = ""; - private final String address = ""; - private String pubmedid = ""; - private String doi = ""; - private String pii = ""; - private String pmc = ""; - private String majorTopic = ""; - private String minorTopics = ""; - private String language = ""; - private String pst = ""; - private final List authors = new ArrayList<>(); - private final Set descriptors = new TreeSet<>(); // To gather keywords - - private static final String KEYWORD_SEPARATOR = "; "; - - - public List getItems() { - return bibitems; - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes atts) { - // Get the number of attribute - if ("PubmedArticle".equals(localName)) { - // Do nothing - } else if ("ArticleTitle".equals(localName)) { - inTitle = true; - title = ""; - } else if ("PubDate".equals(localName)) { - inPubDate = true; - } else if ("Year".equals(localName) && inPubDate) { - inYear = true; - } else if ("MedlineDate".equals(localName) && inPubDate) { - inMedlineDate = true; - } // medline date does not have 4 digit dates instead it has multiyear etc - else if ("MedlineTA".equals(localName)) { - inJournal = true; - journal = ""; - } //journal name - else if ("Month".equals(localName) && inPubDate) { - inMonth = true; - } else if ("Volume".equals(localName)) { - inVolume = true; - } else if ("Language".equals(localName)) { - inLanguage = true; - } else if ("PublicationStatus".equals(localName)) { - inPst = true; - } else if ("AuthorList".equals(localName)) { - inAuthorList = true; - authors.clear(); - } else if ("MeshHeading".equals(localName)) { - inMeshHeader = true; - majorTopic = ""; - minorTopics = ""; - } else if ("DescriptorName".equals(localName)) { - inDescriptorName = true; - } else if ("QualifierName".equals(localName)) { - inQualifierName = true; - } else if ("Author".equals(localName)) { - inAuthor = true; - author = ""; - } else if ("CollectiveName".equals(localName)) { - inForename = true; - forename = ""; - } // Morten A. 20040513. - else if ("PMID".equals(localName)) { - // Set PMID only once, because there can be tags later on that - // contain IDs of different articles. - if (pubmedid.isEmpty()) { - inPubMedID = true; - pubmedid = ""; - } - } else if ("LastName".equals(localName)) { - inLastName = true; - lastName = ""; - } else if ("ForeName".equals(localName) || "FirstName".equals(localName)) { - inForename = true; - forename = ""; - } else if ("Suffix".equals(localName)) { - inSuffix = true; - suffix = ""; - } else if ("Issue".equals(localName)) { - inIssue = true; - } else if ("MedlinePgn".equals(localName)) { - inMedlinePgn = true; - } //pagenumber - else if ("URL".equals(localName)) { - inUrl = true; - } else if ("Initials".equals(localName)) { - inInitials = true; - } else if ("AbstractText".equals(localName)) { - inAbstractText = true; - } else if ("ArticleId".equals(localName)) { - for (int i = 0; i < atts.getLength(); i++) { - String value = atts.getValue(i); - if ("doi".equals(value)) { - inDoi = true; - } else if ("pii".equals(value)) { - inPii = true; - } else if ("pmc".equals(value)) { - inPmc = true; - } - - } - } else if ("Affiliation".equals(localName)) { - inAffiliation = true; - } - - } - - private String join(Object[] sa, String delim) { - StringBuilder sb = new StringBuilder(); - sb.append(sa[0]); - for (int i = 1; i < sa.length; i++) - { - sb.append(delim); - sb.append(sa[i]); - } - return sb.toString(); - } - - @Override - public void endElement(String uri, String localName, String qName) { - if ("PubmedArticle".equals(localName)) { - //bibitems.add( new Bibitem(null, makeBibtexString(), Globals.nextKey(),"-1" ) ); - // check if year ="" then give medline date instead - if ("".equals(year) && !"".equals(medlineDate)) { - // multi-year date format - //System.out.println(MedlineDate); - year = medlineDate.substring(0, 4); - //Matcher m = Pattern.compile("\\b[0-9]{4}\\b").matcher(MedlineDate); - //if(m.matches()) - //year = m.group(); - } - - // Build a string from the collected keywords: - StringBuilder sb = new StringBuilder(); - for (Iterator iterator = descriptors.iterator(); iterator.hasNext();) { - String s = iterator.next(); - sb.append(s); - if (iterator.hasNext()) { - sb.append(MedlineHandler.KEYWORD_SEPARATOR); - } - } - String keywords = sb.toString(); - - BibEntry b = new BibEntry(IdGenerator.next(), "article"); // id assumes an existing database so don't create one here - if (!"".equals(author)) { - b.setField("author", - MedlineHandler.UNICODE_CONVERTER.format(author)); - author = ""; - } - if (!"".equals(title)) { - b.setField("title", MedlineHandler.UNICODE_CONVERTER.format(title)); - } - // if (!title.equals("")) b.setField("title",Util.replaceSpecialCharacters(title)); - if (!"".equals(journal)) { - b.setField("journal", journal); - } - if (!"".equals(year)) { - b.setField("year", year); - } - // PENDING jeffrey.kuhn@yale.edu 2005-05-27 : added call to fixPageRange - if (!"".equals(page)) { - b.setField("pages", fixPageRange(page)); - } - if (!"".equals(volume)) { - b.setField("volume", volume); - } - if (!"".equals(language)) { - b.setField("language", language); - } - if (!"".equals(pst)) { - b.setField("medline-pst", pst); - } - if (!"".equals(abstractText)) { - b.setField("abstract", abstractText.replace("%", "\\%")); - } - if (!"".equals(keywords)) { - b.setField("keywords", keywords); - } - if (!"".equals(month)) { - b.setField("month", month); - } - //if (!url.equals("")) b.setField("url",url); - if (!"".equals(number)) { - b.setField("number", number); - } - - if (!"".equals(doi)) { - b.setField("doi", doi); - b.setField("url", "http://dx.doi.org/" + doi); - } - if (!"".equals(pii)) { - b.setField("pii", pii); - } - if (!"".equals(pmc)) { - b.setField("pmc", pmc); - } - if (!"".equals(affiliation)) { - b.setField("institution", affiliation.replace("#", "\\#")); - } - - // PENDING jeffrey.kuhn@yale.edu 2005-05-27 : added "pmid" bibtex field - // Older references do not have doi entries, but every - // medline entry has a unique pubmed ID (aka primary ID). - // Add a bibtex field for the pubmed ID for future use. - if (!"".equals(pubmedid)) { - b.setField("pmid", pubmedid); - } - - bibitems.add(b); - - abstractText = ""; - author = ""; - title = ""; - journal = ""; - keywords = ""; - doi = ""; - pii = ""; - pmc = ""; - year = ""; - forename = ""; - lastName = ""; - suffix = ""; - abstractText = ""; - affiliation = ""; - pubmedid = ""; - majorTopic = ""; - minorTopics = ""; - month = ""; - volume = ""; - language = ""; - pst = ""; - lastname = ""; - suffix = ""; - initials = ""; - number = ""; - page = ""; - String medlineID = ""; - String url = ""; - medlineDate = ""; - descriptors.clear(); - } - - else if ("ArticleTitle".equals(localName)) { - inTitle = false; - } - else if ("PubDate".equals(localName)) { - inPubDate = false; - } - else if ("Year".equals(localName)) { - inYear = false; - } - else if ("PMID".equals(localName)) { - inPubMedID = false; - } - else if ("MedlineDate".equals(localName)) { - inMedlineDate = false; - } - else if ("MedlineTA".equals(localName)) { - inJournal = false; - } //journal name - else if ("Month".equals(localName)) { - inMonth = false; - } - else if ("Volume".equals(localName)) { - inVolume = false; - } - else if ("Language".equals(localName)) { - inLanguage = false; - } - else if ("PublicationStatus".equals(localName)) { - inPst = false; - } - else if ("AuthorList".equals(localName)) { - author = join(authors.toArray(), " and "); - inAuthorList = false; - } - else if ("Author".equals(localName)) { - // forename sometimes has initials with " " in middle: is pattern [A-Z] [A-Z] - // when above is the case replace it with initials - if ((forename.length() == 3) && (forename.charAt(1) == ' ')) { - forename = initials; - } - - // Put together name with last name first, and enter suffix in between if present: - if (lastname.indexOf(' ') > 0) { - author = "{" + lastname + "}"; - } else { - author = lastname; - } - - if (!suffix.isEmpty()) { - author = author + ", " + suffix; - } - if (!forename.isEmpty()) { - author = author + ", " + forename; - } - - //author = initials + " " + lastname; - authors.add(author); - inAuthor = false; - forename = ""; - initials = ""; - lastname = ""; - suffix = ""; - } - else if ("DescriptorName".equals(localName)) { - inDescriptorName = false; - } else if ("QualifierName".equals(localName)) { - inQualifierName = false; - } else if ("MeshHeading".equals(localName)) { - inMeshHeader = false; - if ("".equals(minorTopics)) { - descriptors.add(majorTopic); - } else { - descriptors.add(majorTopic + ", " + minorTopics); - } - } - else if ("LastName".equals(localName)) { - inLastName = false; - } - else if ("Suffix".equals(localName)) { - inSuffix = false; - } - else if ("ForeName".equals(localName) || "FirstName".equals(localName)) { - inForename = false; - } - else if ("Issue".equals(localName)) { - inIssue = false; - } - else if ("MedlinePgn".equals(localName)) { - inMedlinePgn = false; - }//pagenumber - else if ("URL".equals(localName)) { - inUrl = false; - } - else if ("Initials".equals(localName)) { - //initials= '.' + initials + '.'; - inInitials = false; - } - else if ("AbstractText".equals(localName)) { - inAbstractText = false; - } - else if ("Affiliation".equals(localName)) { - inAffiliation = false; - } - else if ("ArticleId".equals(localName)) { - if (inDoi) { - inDoi = false; - } else if (inPii) { - inPii = false; - } else if (inPmc) { - inPmc = false; - } - } - } - - @Override - public void characters(char[] data, int start, int length) { - - // if stack is not ready, data is not content of recognized element - boolean inURL = false; - boolean inMedlineID = false; - if (inTitle) { - title += new String(data, start, length); - } - else if (inYear) { - year += new String(data, start, length); - } - else if (inJournal) { - journal += new String(data, start, length); - } - else if (inMonth) { - month += new String(data, start, length); - } - else if (inVolume) { - volume += new String(data, start, length); - } - else if (inLanguage) { - language += new String(data, start, length).toLowerCase(); - } - else if (inPst) { - pst += new String(data, start, length); - } - else if (inLastName) { - lastname += new String(data, start, length); - } - else if (inSuffix) { - suffix += new String(data, start, length); - } - else if (inInitials) { - initials += new String(data, start, length); - } - else if (inIssue) { - number += new String(data, start, length); - } - else if (inMedlinePgn) { - page += new String(data, start, length); - } - else if (inMedlineID) { - String medlineID = new String(data, start, length); - } - else if (inURL) { - String url = new String(data, start, length); - } - else if (inPubMedID) { - pubmedid = new String(data, start, length); - } - else if (inQualifierName) { - if (!"".equals(minorTopics)) { - minorTopics = minorTopics + "/"; - } - minorTopics = minorTopics + new String(data, start, length); - } - else if (inDescriptorName) { - majorTopic = new String(data, start, length); - } - - //keywords += new String(data,start,length) + ", "; - else if (inForename) { - forename += new String(data, start, length); - //System.out.println("IN FORENAME: " + forename); - } - else if (inAbstractText) { - abstractText += new String(data, start, length); - } - else if (inMedlineDate) { - medlineDate += new String(data, start, length); - } - else if (inDoi) { - doi = new String(data, start, length); - } - else if (inPii) { - pii = new String(data, start, length); - } - else if (inPmc) { - pmc = new String(data, start, length); - } - else if (inAffiliation) { - affiliation = new String(data, start, length); - } - } - - // PENDING jeffrey.kuhn@yale.edu 2005-05-27 : added fixPageRange method - // Convert medline page ranges from short form to full form. - // Medline reports page ranges in a shorthand format. - // The last page is reported using only the digits which - // differ from the first page. - // i.e. 12345-51 refers to the actual range 12345-12351 - private String fixPageRange(String pageRange) { - int minusPos = pageRange.indexOf('-'); - if (minusPos < 0) { - return pageRange; - } - String first = pageRange.substring(0, minusPos).trim(); - String last = pageRange.substring(minusPos + 1).trim(); - int llast = last.length(); - int lfirst = first.length(); - if (llast < lfirst) { - last = first.substring(0, lfirst - llast) + last; - } - return first + "--" + last; - } -} diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java index f180264fae6a..1eb6b5880122 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java @@ -16,33 +16,88 @@ package net.sf.jabref.importer.fileformat; import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Objects; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.importer.fileformat.medline.Abstract; +import net.sf.jabref.importer.fileformat.medline.AbstractText; +import net.sf.jabref.importer.fileformat.medline.AffiliationInfo; +import net.sf.jabref.importer.fileformat.medline.ArticleTitle; +import net.sf.jabref.importer.fileformat.medline.Author; +import net.sf.jabref.importer.fileformat.medline.AuthorList; +import net.sf.jabref.importer.fileformat.medline.Book; +import net.sf.jabref.importer.fileformat.medline.BookDocument; +import net.sf.jabref.importer.fileformat.medline.BookTitle; +import net.sf.jabref.importer.fileformat.medline.Chemical; +import net.sf.jabref.importer.fileformat.medline.ContributionDate; +import net.sf.jabref.importer.fileformat.medline.DateCompleted; +import net.sf.jabref.importer.fileformat.medline.DateCreated; +import net.sf.jabref.importer.fileformat.medline.DateRevised; +import net.sf.jabref.importer.fileformat.medline.ELocationID; +import net.sf.jabref.importer.fileformat.medline.GeneSymbolList; +import net.sf.jabref.importer.fileformat.medline.GeneralNote; +import net.sf.jabref.importer.fileformat.medline.ISSN; +import net.sf.jabref.importer.fileformat.medline.Investigator; +import net.sf.jabref.importer.fileformat.medline.InvestigatorList; +import net.sf.jabref.importer.fileformat.medline.Journal; +import net.sf.jabref.importer.fileformat.medline.JournalIssue; +import net.sf.jabref.importer.fileformat.medline.Keyword; +import net.sf.jabref.importer.fileformat.medline.KeywordList; +import net.sf.jabref.importer.fileformat.medline.MedlineCitation; +import net.sf.jabref.importer.fileformat.medline.MedlineJournalInfo; +import net.sf.jabref.importer.fileformat.medline.MeshHeading; +import net.sf.jabref.importer.fileformat.medline.MeshHeadingList; +import net.sf.jabref.importer.fileformat.medline.OtherID; +import net.sf.jabref.importer.fileformat.medline.Pagination; +import net.sf.jabref.importer.fileformat.medline.PersonalNameSubject; +import net.sf.jabref.importer.fileformat.medline.PersonalNameSubjectList; +import net.sf.jabref.importer.fileformat.medline.PubDate; +import net.sf.jabref.importer.fileformat.medline.PublicationType; +import net.sf.jabref.importer.fileformat.medline.Publisher; +import net.sf.jabref.importer.fileformat.medline.PubmedArticle; +import net.sf.jabref.importer.fileformat.medline.PubmedArticleSet; +import net.sf.jabref.importer.fileformat.medline.PubmedBookArticle; +import net.sf.jabref.importer.fileformat.medline.PubmedBookArticleSet; +import net.sf.jabref.importer.fileformat.medline.PubmedBookData; +import net.sf.jabref.importer.fileformat.medline.QualifierName; +import net.sf.jabref.importer.fileformat.medline.Section; +import net.sf.jabref.importer.fileformat.medline.Sections; +import net.sf.jabref.importer.fileformat.medline.Text; +import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.IdGenerator; +import com.google.common.base.Joiner; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.xml.sax.InputSource; /** - * Importer for the Medline format. + * Importer for the Medline/Pubmed format. * * check here for details on the format - * http://www.nlm.nih.gov/bsd/mms/medlineelements.html + * https://www.nlm.nih.gov/bsd/licensee/elements_descriptions.html */ public class MedlineImporter extends ImportFormat { private static final Log LOGGER = LogFactory.getLog(MedlineImporter.class); + private static final String KEYWORD_SEPARATOR = "; "; + + private static final Locale ENGLISH = Locale.ENGLISH; @Override @@ -71,7 +126,8 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { int i = 0; while (((str = reader.readLine()) != null) && (i < 50)) { - if (str.toLowerCase().contains("")) { + if (str.toLowerCase(ENGLISH).contains("") + || str.toLowerCase(ENGLISH).contains("")) { return true; } @@ -84,50 +140,535 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { public ParserResult importDatabase(BufferedReader reader) throws IOException { Objects.requireNonNull(reader); - // Obtain a factory object for creating SAX parsers - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); - - // Configure the factory object to specify attributes of the parsers it - // creates - parserFactory.setValidating(true); - parserFactory.setNamespaceAware(true); - - // Now create a SAXParser object List bibItems = new ArrayList<>(); + try { - SAXParser parser = parserFactory.newSAXParser(); // May throw - // exceptions - MedlineHandler handler = new MedlineHandler(); - // Start the parser. It reads the file and calls methods of the - // handler. - parser.parse(new InputSource(reader), handler); - - // Switch this to true if you want to make a local copy for testing. - if (false) { - reader.reset(); - try (FileOutputStream out = new FileOutputStream(new File("/home/alver/ut.txt"))) { - int c; - while ((c = reader.read()) != -1) { - out.write((char) c); + JAXBContext context = JAXBContext.newInstance("net.sf.jabref.importer.fileformat.medline"); + XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); + XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(reader); + + //go to the root element + while (!xmlStreamReader.isStartElement()) { + xmlStreamReader.next(); + } + + Unmarshaller unmarshaller = context.createUnmarshaller(); + Object unmarshalledObject = unmarshaller.unmarshal(xmlStreamReader); + + //check whether we have an article set, an article, a book article or a book article set + if (unmarshalledObject instanceof PubmedArticleSet) { + PubmedArticleSet articleSet = (PubmedArticleSet) unmarshalledObject; + for (Object article : articleSet.getPubmedArticleOrPubmedBookArticle()) { + if (article instanceof PubmedArticle) { + PubmedArticle currentArticle = (PubmedArticle) article; + parseArticle(currentArticle, bibItems); + } + if (article instanceof PubmedBookArticle) { + PubmedBookArticle currentArticle = (PubmedBookArticle) article; + parseBookArticle(currentArticle, bibItems); } } + } else if (unmarshalledObject instanceof PubmedArticle) { + PubmedArticle article = (PubmedArticle) unmarshalledObject; + parseArticle(article, bibItems); + } else if (unmarshalledObject instanceof PubmedBookArticle) { + PubmedBookArticle currentArticle = (PubmedBookArticle) unmarshalledObject; + parseBookArticle(currentArticle, bibItems); + } else { + PubmedBookArticleSet bookArticleSet = (PubmedBookArticleSet) unmarshalledObject; + for (PubmedBookArticle bookArticle : bookArticleSet.getPubmedBookArticle()) { + parseBookArticle(bookArticle, bibItems); + } } - - // When you're done, report the results stored by your handler - // object - bibItems.addAll(handler.getItems()); - } catch (javax.xml.parsers.ParserConfigurationException e) { - LOGGER.error("Error with XML parser configuration", e); - return ParserResult.fromErrorMessage(e.getLocalizedMessage()); - } catch (org.xml.sax.SAXException e) { - LOGGER.error("Error during XML parsing", e); - return ParserResult.fromErrorMessage(e.getLocalizedMessage()); - } catch (IOException e) { - LOGGER.error("Error during file import", e); + } catch (JAXBException | XMLStreamException e) { + LOGGER.debug("could not parse document", e); return ParserResult.fromErrorMessage(e.getLocalizedMessage()); } - return new ParserResult(bibItems); } + private void parseBookArticle(PubmedBookArticle currentArticle, List bibItems) { + HashMap fields = new HashMap<>(); + if (currentArticle.getBookDocument() != null) { + BookDocument bookDocument = currentArticle.getBookDocument(); + fields.put("pmid", bookDocument.getPMID().getContent()); + if (bookDocument.getDateRevised() != null) { + DateRevised dateRevised = bookDocument.getDateRevised(); + addDateRevised(fields, dateRevised); + } + if (bookDocument.getAbstract() != null) { + Abstract abs = bookDocument.getAbstract(); + addAbstract(fields, abs); + } + if (bookDocument.getPagination() != null) { + Pagination pagination = bookDocument.getPagination(); + addPagination(fields, pagination); + } + if (bookDocument.getSections() != null) { + ArrayList result = new ArrayList<>(); + Sections sections = bookDocument.getSections(); + for (Section section : sections.getSection()) { + for (Serializable content : section.getSectionTitle().getContent()) { + if (content instanceof String) { + result.add((String) content); + } + } + } + fields.put("sections", join(result, "; ")); + } + if (bookDocument.getKeywordList() != null) { + addKeyWords(fields, bookDocument.getKeywordList()); + } + if (bookDocument.getContributionDate() != null) { + addContributionDate(fields, bookDocument.getContributionDate()); + } + if (bookDocument.getPublicationType() != null) { + List result = new ArrayList<>(); + for (PublicationType type : bookDocument.getPublicationType()) { + if (type.getContent() != null) { + result.add(type.getContent()); + } + } + fields.put("pubtype", join(result, ", ")); + } + if (bookDocument.getArticleTitle() != null) { + ArticleTitle articleTitle = bookDocument.getArticleTitle(); + ArrayList titles = new ArrayList<>(); + for (Serializable content : articleTitle.getContent()) { + if (content instanceof String) { + titles.add((String) content); + } + } + fields.put("article", join(titles, ", ")); + } + if (bookDocument.getBook() != null) { + addBookInformation(fields, bookDocument.getBook()); + } + } + + if (currentArticle.getPubmedBookData() != null) { + PubmedBookData bookData = currentArticle.getPubmedBookData(); + putIfValueNotNull(fields, "pubstatus", bookData.getPublicationStatus()); + } + + BibEntry entry = new BibEntry(IdGenerator.next(), "article"); + entry.setField(fields); + + bibItems.add(entry); + } + + private void addBookInformation(HashMap fields, Book book) { + if (book.getPublisher() != null) { + Publisher publisher = book.getPublisher(); + putIfValueNotNull(fields, "publocation", publisher.getPublisherLocation()); + putStringFromSerializableList(fields, "publisher", publisher.getPublisherName().getContent()); + } + if (book.getBookTitle() != null) { + BookTitle title = book.getBookTitle(); + putStringFromSerializableList(fields, "title", title.getContent()); + } + if (book.getPubDate() != null) { + addPubDate(fields, book.getPubDate()); + } + if (book.getAuthorList() != null) { + List authorLists = book.getAuthorList(); + //authorLists size should be one + if (authorLists.size() == 1) { + for (AuthorList authorList : authorLists) { + handleAuthors(fields, authorList); + } + } else { + LOGGER.info(String.format("Size of authorlist was %s", authorLists.size())); + } + } + + putIfValueNotNull(fields, "volume", book.getVolume()); + putIfValueNotNull(fields, "edition", book.getEdition()); + putIfValueNotNull(fields, "medium", book.getMedium()); + putIfValueNotNull(fields, "reportnumber", book.getReportNumber()); + + if (book.getELocationID() != null) { + for (ELocationID id : book.getELocationID()) { + addElocationID(fields, id); + } + } + if (book.getIsbn() != null) { + fields.put("isbn", join(book.getIsbn(), ", ")); + } + } + + private void putStringFromSerializableList(HashMap fields, String medlineKey, + List contentList) { + StringBuilder result = new StringBuilder(); + for (Serializable content : contentList) { + if (content instanceof String) { + result.append((String) content); + } + } + if (result.length() > 0) { + fields.put(medlineKey, result.toString()); + } + } + + private void addContributionDate(HashMap fields, ContributionDate contributionDate) { + if ((contributionDate.getDay() != null) && (contributionDate.getMonth() != null) + && (contributionDate.getYear() != null)) { + String result = convertToDateFormat(contributionDate.getYear(), contributionDate.getMonth(), + contributionDate.getDay()); + fields.put("contribution", result); + } + } + + private String convertToDateFormat(String year, String month, String day) { + return String.format("%s-%s-%s", year, month, day); + } + + private void parseArticle(PubmedArticle article, List bibItems) { + HashMap fields = new HashMap<>(); + + if (article.getPubmedData() != null) { + if (article.getMedlineCitation().getDateRevised() != null) { + DateRevised dateRevised = article.getMedlineCitation().getDateRevised(); + addDateRevised(fields, dateRevised); + putIfValueNotNull(fields, "pubstatus", article.getPubmedData().getPublicationStatus()); + } + } + if (article.getMedlineCitation() != null) { + MedlineCitation medlineCitation = article.getMedlineCitation(); + + fields.put("status", medlineCitation.getStatus()); + DateCreated dateCreated = medlineCitation.getDateCreated(); + fields.put("created", + convertToDateFormat(dateCreated.getYear(), dateCreated.getMonth(), dateCreated.getDay())); + fields.put("pubmodel", medlineCitation.getArticle().getPubModel()); + + if (medlineCitation.getDateCompleted() != null) { + DateCompleted dateCompleted = medlineCitation.getDateCompleted(); + fields.put("completed", + convertToDateFormat(dateCompleted.getYear(), dateCompleted.getMonth(), dateCompleted.getDay())); + } + + fields.put("pmid", medlineCitation.getPMID().getContent()); + fields.put("owner", medlineCitation.getOwner()); + + addArticleInformation(fields, medlineCitation.getArticle().getContent()); + + MedlineJournalInfo medlineJournalInfo = medlineCitation.getMedlineJournalInfo(); + putIfValueNotNull(fields, "country", medlineJournalInfo.getCountry()); + putIfValueNotNull(fields, "journal-abbreviation", medlineJournalInfo.getMedlineTA()); + putIfValueNotNull(fields, "nlm-id", medlineJournalInfo.getNlmUniqueID()); + putIfValueNotNull(fields, "issn-linking", medlineJournalInfo.getISSNLinking()); + if (medlineCitation.getChemicalList() != null) { + if (medlineCitation.getChemicalList().getChemical() != null) { + addChemicals(fields, medlineCitation.getChemicalList().getChemical()); + } + } + if (medlineCitation.getCitationSubset() != null) { + fields.put("citation-subset", join(medlineCitation.getCitationSubset(), ", ")); + } + if (medlineCitation.getGeneSymbolList() != null) { + addGeneSymbols(fields, medlineCitation.getGeneSymbolList()); + } + if (medlineCitation.getMeshHeadingList() != null) { + addMeashHeading(fields, medlineCitation.getMeshHeadingList()); + } + putIfValueNotNull(fields, "references", medlineCitation.getNumberOfReferences()); + if (medlineCitation.getPersonalNameSubjectList() != null) { + addPersonalNames(fields, medlineCitation.getPersonalNameSubjectList()); + } + if (medlineCitation.getOtherID() != null) { + addOtherId(fields, medlineCitation.getOtherID()); + } + if (medlineCitation.getKeywordList() != null) { + addKeyWords(fields, medlineCitation.getKeywordList()); + } + if (medlineCitation.getSpaceFlightMission() != null) { + fields.put("space-flight-mission", join(medlineCitation.getSpaceFlightMission(), ", ")); + } + if (medlineCitation.getInvestigatorList() != null) { + addInvestigators(fields, medlineCitation.getInvestigatorList()); + } + if (medlineCitation.getGeneralNote() != null) { + addNotes(fields, medlineCitation.getGeneralNote()); + } + } + + BibEntry entry = new BibEntry(IdGenerator.next(), "article"); + entry.setField(fields); + + bibItems.add(entry); + } + + private void addNotes(HashMap fields, List generalNote) { + List notes = new ArrayList<>(); + for (GeneralNote note : generalNote) { + if (note != null) { + notes.add(note.getContent()); + } + } + fields.put("note", join(notes, ", ")); + } + + private void addInvestigators(HashMap fields, InvestigatorList investigatorList) { + List investigatorNames = new ArrayList<>(); + List affiliationInfos = new ArrayList<>(); + String name = ""; + // add the investigators like the authors + if (investigatorList.getInvestigator() != null) { + List investigators = investigatorList.getInvestigator(); + for (Investigator investigator : investigators) { + name = investigator.getLastName(); + if (investigator.getForeName() != null) { + name += ", " + investigator.getForeName(); + } + investigatorNames.add(name); + + //now add the affiliation info + if (investigator.getAffiliationInfo() != null) { + for (AffiliationInfo info : investigator.getAffiliationInfo()) { + for (Serializable affiliation : info.getAffiliation().getContent()) { + if (affiliation instanceof String) { + affiliationInfos.add((String) affiliation); + } + } + } + fields.put("affiliation", join(affiliationInfos, ", ")); + } + } + fields.put("investigator", join(investigatorNames, " and ")); + } + } + + private void addKeyWords(HashMap fields, List allKeywordLists) { + List keywordStrings = new ArrayList<>(); + //add keywords to the list + for (KeywordList keywordList : allKeywordLists) { + for (Keyword keyword : keywordList.getKeyword()) { + for (Serializable content : keyword.getContent()) { + if (content instanceof String) { + keywordStrings.add((String) content); + } + } + } + } + //Check whether MeshHeadingList exist or not + if (fields.get("keywords") == null) { + fields.put("keywords", join(keywordStrings, KEYWORD_SEPARATOR)); + } else { + if (keywordStrings.size() > 0) { + //if it exists, combine the MeshHeading with the keywords + String result = join(keywordStrings, "; "); + result = fields.get("keywords") + KEYWORD_SEPARATOR + result; + fields.put("keywords", result); + } + } + } + + private void addOtherId(HashMap fields, List otherID) { + for (OtherID id : otherID) { + if ((id.getSource() != null) && (id.getContent() != null)) { + fields.put(id.getSource(), id.getContent()); + } + } + } + + private void addPersonalNames(HashMap fields, PersonalNameSubjectList personalNameSubjectList) { + if (fields.get("author") == null) { + //if no authors appear, then add the personal names as authors + List personalNames = new ArrayList<>(); + if (personalNameSubjectList.getPersonalNameSubject() != null) { + List personalNameSubject = personalNameSubjectList.getPersonalNameSubject(); + for (PersonalNameSubject personalName : personalNameSubject) { + String name = personalName.getLastName(); + if (personalName.getForeName() != null) { + name += ", " + personalName.getForeName().toString(); + } + personalNames.add(name); + } + fields.put("author", join(personalNames, " and ")); + } + } + } + + private void addMeashHeading(HashMap fields, MeshHeadingList meshHeadingList) { + ArrayList keywords = new ArrayList<>(); + for (MeshHeading keyword : meshHeadingList.getMeshHeading()) { + String result = keyword.getDescriptorName().getContent(); + if (keyword.getQualifierName() != null) { + for (QualifierName qualifier : keyword.getQualifierName()) { + result += ", " + qualifier.getContent(); + } + } + keywords.add(result); + } + fields.put("keywords", join(keywords, KEYWORD_SEPARATOR)); + } + + private void addGeneSymbols(HashMap fields, GeneSymbolList geneSymbolList) { + List geneSymbols = geneSymbolList.getGeneSymbol(); + fields.put("gene-symbols", join(geneSymbols, ", ")); + } + + private void addChemicals(HashMap fields, List chemicals) { + List chemicalNames = new ArrayList<>(); + for (Chemical chemical : chemicals) { + if (chemical != null) { + chemicalNames.add(chemical.getNameOfSubstance().getContent()); + } + } + fields.put("chemicals", join(chemicalNames, ", ")); + } + + private void addArticleInformation(HashMap fields, List content) { + for (Object object : content) { + if (object instanceof Journal) { + Journal journal = (Journal) object; + putIfValueNotNull(fields, "journal", journal.getTitle()); + + ISSN issn = journal.getISSN(); + putIfValueNotNull(fields, "issn", issn.getContent()); + + JournalIssue journalIssue = journal.getJournalIssue(); + putIfValueNotNull(fields, "volume", journalIssue.getVolume()); + putIfValueNotNull(fields, "issue", journalIssue.getIssue()); + + addPubDate(fields, journalIssue.getPubDate()); + } else if (object instanceof ArticleTitle) { + ArticleTitle articleTitle = (ArticleTitle) object; + fields.put("title", StringUtil.stripBrackets(articleTitle.getContent().toString())); + } else if (object instanceof Pagination) { + Pagination pagination = (Pagination) object; + addPagination(fields, pagination); + } else if (object instanceof ELocationID) { + ELocationID eLocationID = (ELocationID) object; + addElocationID(fields, eLocationID); + } else if (object instanceof Abstract) { + Abstract abs = (Abstract) object; + addAbstract(fields, abs); + } else if (object instanceof AuthorList) { + AuthorList authors = (AuthorList) object; + handleAuthors(fields, authors); + } + } + } + + private void addElocationID(HashMap fields, ELocationID eLocationID) { + if ("doi".equals(eLocationID.getEIdType())) { + fields.put("doi", eLocationID.getContent()); + } + if ("pii".equals(eLocationID.getEIdType())) { + fields.put("pii", eLocationID.getContent()); + } + } + + private void addPubDate(HashMap fields, PubDate pubDate) { + if (pubDate.getYear() == null) { + //if year of the pubdate is null, the medlineDate shouldn't be null + fields.put("year", extractYear(pubDate.getMedlineDate())); + } else { + fields.put("year", pubDate.getYear()); + if (pubDate.getMonth() != null) { + fields.put("month", pubDate.getMonth()); + } else if (pubDate.getSeason() != null) { + fields.put("season", pubDate.getSeason()); + } + } + } + + private void addAbstract(HashMap fields, Abstract abs) { + putIfValueNotNull(fields, "copyright", abs.getCopyrightInformation()); + List abstractText = new ArrayList<>(); + for (AbstractText text : abs.getAbstractText()) { + for (Serializable textContent : text.getContent()) { + if (textContent instanceof String) { + abstractText.add((String) textContent); + } + } + } + fields.put("abstract", join(abstractText, " ")); + } + + private void addPagination(HashMap fields, Pagination pagination) { + String startPage = ""; + String endPage = ""; + for (JAXBElement element : pagination.getContent()) { + if ("MedlinePgn".equals(element.getName().getLocalPart())) { + putIfValueNotNull(fields, "pages", fixPageRange(element.getValue())); + } else if ("StartPage".equals(element.getName().getLocalPart())) { + //it could happen, that the article has only a start page + startPage = element.getValue() + endPage; + putIfValueNotNull(fields, "pages", startPage); + } else if ("EndPage".equals(element.getName().getLocalPart())) { + endPage = element.getValue(); + //but it should not happen, that a endpage appears without startpage + fields.put("pages", fixPageRange(startPage + "-" + endPage)); + } + } + } + + private String extractYear(String medlineDate) { + //The year of the medlineDate should be the first 4 digits + return medlineDate.substring(0, 4); + } + + private void handleAuthors(HashMap fields, AuthorList authors) { + List authorNames = new ArrayList<>(); + for (Author author : authors.getAuthor()) { + if (author.getCollectiveName() != null) { + Text collectiveNames = author.getCollectiveName(); + for (Serializable content : collectiveNames.getContent()) { + if (content instanceof String) { + authorNames.add((String) content); + } + } + } else { + String authorName = author.getLastName(); + if (author.getForeName() != null) { + authorName += ", " + author.getForeName(); + } + authorNames.add(authorName); + } + } + fields.put("author", join(authorNames, " and ")); + } + + private static String join(List list, String string) { + return Joiner.on(string).join(list); + } + + private void addDateRevised(HashMap fields, DateRevised dateRevised) { + if ((dateRevised.getDay() != null) && (dateRevised.getMonth() != null) && (dateRevised.getYear() != null)) { + fields.put("revised", + convertToDateFormat(dateRevised.getYear(), dateRevised.getMonth(), dateRevised.getDay())); + } + } + + private void putIfValueNotNull(HashMap fields, String medlineKey, String value) { + if (value != null) { + fields.put(medlineKey, value); + } + } + + /** + * Convert medline page ranges from short form to full form. + * Medline reports page ranges in a shorthand format. + * The last page is reported using only the digits which + * differ from the first page. + * i.e. 12345-51 refers to the actual range 12345-12351 + */ + private String fixPageRange(String pageRange) { + int minusPos = pageRange.indexOf('-'); + if (minusPos < 0) { + return pageRange; + } + String startPage = pageRange.substring(0, minusPos).trim(); + String endPage = pageRange.substring(minusPos + 1).trim(); + int lengthOfEndPage = endPage.length(); + int lengthOfStartPage = startPage.length(); + if (lengthOfEndPage < lengthOfStartPage) { + endPage = startPage.substring(0, lengthOfStartPage - lengthOfEndPage) + endPage; + } + return startPage + "--" + endPage; + } + } diff --git a/src/main/resources/xjc/medline/bookdoc_160101.xsd b/src/main/resources/xjc/medline/bookdoc_160101.xsd new file mode 100644 index 000000000000..fc7062d98f2d --- /dev/null +++ b/src/main/resources/xjc/medline/bookdoc_160101.xsd @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/xjc/medline/medline.xsd b/src/main/resources/xjc/medline/medline.xsd new file mode 100644 index 000000000000..9c2f73a5bdd1 --- /dev/null +++ b/src/main/resources/xjc/medline/medline.xsd @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/xjc/medline/nlmmedlinecitationset_160101.xsd b/src/main/resources/xjc/medline/nlmmedlinecitationset_160101.xsd new file mode 100644 index 000000000000..bdf251007b7c --- /dev/null +++ b/src/main/resources/xjc/medline/nlmmedlinecitationset_160101.xsd @@ -0,0 +1,861 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java index 2c4e170ed07c..790c70168cdc 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTest.java @@ -7,7 +7,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -58,12 +57,6 @@ public void setUp() throws Exception { this.importer = new MedlineImporter(); } - @Test - public void testGetItemsEmpty() { - MedlineHandler handler = new MedlineHandler(); - assertEquals(Collections.emptyList(), handler.getItems()); - } - @Test public void testGetFormatName() { assertEquals("Medline", importer.getFormatName()); diff --git a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java index 2cf5d5e25f11..ccf40027d23b 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/MedlineImporterTestFiles.java @@ -19,7 +19,6 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -51,7 +50,8 @@ public static Collection files() throws IOException { try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(FILEFORMAT_PATH))) { stream.forEach(files::add); } - return files.stream().filter(n -> n.getFileName().toString().startsWith("MedlineImporterTest") && n.getFileName().toString().endsWith(".xml")) + return files.stream().filter(n -> n.getFileName().toString().startsWith("MedlineImporterTest") + && n.getFileName().toString().endsWith(".xml")) .collect(Collectors.toList()); } @@ -61,7 +61,6 @@ public void testIsRecognizedFormat() throws IOException { } @Test - @Ignore public void testImportEntries() throws IOException { List medlineEntries = medlineImporter.importDatabase(importFile, Charset.defaultCharset()).getDatabase().getEntries(); String bibFileName = importFile.getFileName().toString().replace(".xml", ".bib"); diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib index d0414750291d..af140a04f97a 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.bib @@ -1,14 +1,23 @@ -% Encoding: UTF-8 - @article{, abstract = {This abstract is a dummy.}, - author = {Rhein, Joshua and Bahr, Nathan C. and Hemmert, Andrew C. and Cloud, Joann L. and Bellamkonda, Satya and Oswald, Cody and Lo, Eric and Nabeta, Henry and Kiggundu, Reuben and Akampurira, Andrew and Musubire, Abdu and Williams, Darlisha A. and Meya, David B. and Boulware, David R. and , A. S. T. R. O.-C. M. Team}, - institution = {Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA.}, - journal = {Diagn Microbiol Infect Dis}, - language = {eng}, - medline-pst = {aheadofprint}, + author = {Rhein, Joshua and Bahr, Nathan C and Hemmert, Andrew C and Cloud, Joann L and Bellamkonda, Satya and Oswald, Cody and Lo, Eric and Nabeta, Henry and Kiggundu, Reuben and Akampurira, Andrew and Musubire, Abdu and Williams, Darlisha A and Meya, David B and Boulware, David R and ASTRO-CM Team}, + created = {2015-12-29}, + doi = {10.1016/j.diagmicrobio.2015.11.017}, + issn = {1879-0070}, + issn-linking = {0732-8893}, + journal = {Diagnostic microbiology and infectious disease}, + journal-abbreviation = {Diagn Microbiol Infect Dis}, + keywords = {Cryptococcal meningitis; Diagnostics; HIV; Immunocompromised; Meningitis; PCR}, month = {Dec}, + nlm-id = {8305899}, + owner = {NLM}, + pages = {1234}, + pii = {S0732-8893(15)00432-0}, pmid = {26711635}, + pubmodel = {Print-Electronic}, + pubstatus = {aheadofprint}, + revised = {2015-12-30}, + status = {Publisher}, title = {Diagnostic performance of a multiplex PCR assay for meningitis in an HIV-infected population in Uganda.}, year = {2015} -} \ No newline at end of file +} diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml index 3b64f43676f5..fbe5ea1cffa4 100644 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestArticleID.xml @@ -1,7 +1,4 @@ - - - 26711635 @@ -30,7 +27,7 @@ Diagnostic performance of a multiplex PCR assay for meningitis in an HIV-infected population in Uganda. - + 1234 S0732-8893(15)00432-0 10.1016/j.diagmicrobio.2015.11.017 @@ -225,6 +222,4 @@ - - \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.bib new file mode 100644 index 000000000000..08389c338e33 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.bib @@ -0,0 +1,20 @@ +@article{, + article = {Title for some article}, + author = {National Collaborating Centre for Chronic Conditions (UK)}, + contribution = {2012-03-27}, + doi = {10.3275/8949}, + isbn = {9781860163593}, + month = {02}, + pii = {1223321}, + pmid = {21413195}, + publisher = {Royal College of Physicians (UK)}, + publocation = {London}, + pubstatus = {ppublish}, + pubtype = {Review, Practice Guideline}, + title = {Rheumatoid Arthritis: National Clinical Guideline for Management and Treatment in Adults}, + year = {2009} +}, @article{, + pages = {1831}, + pmid = {21413195}, + revised = {2014-10-11} +} diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.xml new file mode 100644 index 000000000000..462dbaa219f5 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestBookArticleSet.xml @@ -0,0 +1,80 @@ + + + + 21413195 + + NBK51812 + + + + Royal College of Physicians (UK) + London + + Rheumatoid Arthritis: National Clinical Guideline for Management and Treatment in Adults + + 2009 + 02 + + + + National Collaborating Centre for Chronic Conditions (UK) + + + National Institute for Health and Clinical Excellence: Guidance + 9781860163593 + 10.3275/8949 + 1223321 + eng + Review + Practice Guideline + + 2012 + 03 + 27 + + Title for some article + + + + + 2011 + 3 + 18 + 6 + 0 + + + 2011 + 3 + 18 + 6 + 0 + + + 2011 + 3 + 18 + 6 + 0 + + + ppublish + + 21413195 + + + + + + 21413195 + + 2014 + 10 + 11 + + + 1831 + + + + \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.bib new file mode 100644 index 000000000000..b2fbd464d9e4 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.bib @@ -0,0 +1,25 @@ +@article{, + author = {Koop, C Everett}, + chemicals = {Formates, Carbon Dioxide, Aldehyde Oxidoreductases, Methanol}, + citation-subset = {IM}, + completed = {1976-01-16}, + country = {UNITED STATES}, + created = {1976-01-16}, + issn = {0006-2944}, + issn-linking = {0006-2944}, + issue = {2}, + journal = {Biochemical medicine}, + journal-abbreviation = {Biochem Med}, + keywords = {apnea syndrome; cardiovascular disease; self management}, + nlm-id = {0151424}, + owner = {NLM}, + pages = {25--138}, + pmid = {10097079}, + pubmodel = {Print}, + pubstatus = {ppublish}, + revised = {2013-11-21}, + status = {MEDLINE}, + title = {Formate assay in body fluids: application in methanol poisoning.}, + volume = {13}, + year = {1999} +} diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.xml new file mode 100644 index 000000000000..691aa81c4ed8 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestKeywordSingleEntry.xml @@ -0,0 +1,88 @@ + + +1 +10097079 + +1976 +01 +16 + + +1976 +01 +16 + + +2013 +11 +21 + +
    + +0006-2944 + +13 +2 + +1999 Spring + + +Biochemical medicine +Biochem Med + +Formate assay in body fluids: application in methanol poisoning. + +25 +138 + +eng + +Journal Article +Research Support, U.S. Gov't, P.H.S. + +
    + +UNITED STATES +Biochem Med +0151424 +0006-2944 + + + +0 +Formates + + +142M471B3J +Carbon Dioxide + + +EC 1.2.- +Aldehyde Oxidoreductases + + +Y4S76JWI15 +Methanol + + +IM + +apnea syndrome +cardiovascular disease +self management + + + +Koop +C Everett +CE + + +
    + +ppublish + +1 + + +
    diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.bib new file mode 100644 index 000000000000..5e373e01e907 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.bib @@ -0,0 +1,51 @@ +@article{, + abstract = {Just a dummy text. And another dummy}, + affiliation = {Vanderbilt U, Nashville, TN}, + author = {Gibb, F W and Zamm itt, NaN and Beckett, G and Strachan, M W J}, + chemicals = {Iodine Radioisotopes, Thyroxine}, + citation-subset = {IM}, + completed = {2014-07-06}, + copyright = {1992 and something}, + country = {Italy}, + created = {2013-11-07}, + doi = {10.3275/8949}, + gene-symbols = {amino, other symbol}, + investigator = {Wood, D L}, + issn = {1720-8386}, + issn-linking = {0391-4097}, + issue = {9}, + journal = {Journal of endocrinological investigation}, + journal-abbreviation = {J Endocrinol Invest}, + keywords = {Female; Graves Disease, radiotherapy; Humans; Hypothyroidism, etiology; Iodine Radioisotopes, adverse effects, therapeutic use; Retrospective Studies; Thyrotoxicosis, radiotherapy; Thyroxine, blood; Treatment Failure; Weight Gain; keyword; another keyword}, + nlm-id = {7806594}, + note = {a note}, + nrcbl = {14.1}, + owner = {NLM}, + pages = {764--769}, + pii = {1223321}, + pmid = {23633646}, + pubmodel = {Print-Electronic}, + pubstatus = {ppublish}, + references = {23}, + revised = {2015-9-15}, + season = {Spring}, + space-flight-mission = {fly}, + status = {MEDLINE}, + title = {Predictors of treatment failure, incipient hypothyroidism, and weight gain following radioiodine therapy for Graves' thyrotoxicosis.}, + volume = {36}, + year = {2013} +}, @article{, + abstract = {just a dummy.}, + author = {National Collaborating Centre for Chronic Conditions (UK)}, + copyright = {Copyright from somwhere}, + isbn = {9781860163593}, + month = {02}, + pmid = {21413195}, + publisher = {Royal College of Physicians (UK)}, + publocation = {London}, + pubstatus = {ppublish}, + pubtype = {Review, Practice Guideline}, + sections = {Guideline Development Group members; Acknowledgements; Preface; Acronyms, abbreviations and glossary; Development of the Guideline; The Guideline; References; Appendices; Evidence Tables}, + title = {Rheumatoid Arthritis: National Clinical Guideline for Management and Treatment in Adults}, + year = {2009} +} diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.xml new file mode 100644 index 000000000000..de229e56aaf5 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestNbib.xml @@ -0,0 +1,372 @@ + + + + + + 23633646 + + 2013 + 11 + 07 + + + 2014 + 07 + 06 + + + 2015 + 9 + 15 + +
    + + 1720-8386 + + 36 + 9 + + 2013 + Spring + + + Journal of endocrinological investigation + J. Endocrinol. Invest. + + Predictors of treatment failure, incipient hypothyroidism, and weight gain following radioiodine therapy for Graves' thyrotoxicosis. + + 764-9 + + 10.3275/8949 + 1223321 + + Just a dummy text. + And another dummy + 1992 and something + + + + Gibb + F W + FW + Jr + + Edinburgh Centre for Endocrinology, Royal Infirmary of Edinburgh, Little France Crescent, Edinburgh, EH16 4SA, UK. fraser.gibb@nhs.net. + + + + Zamm itt + NaN + NN + + + Beckett + G + GJ + + + Strachan + M W J + MW + + + en + + Journal Article + + + 2013 + 04 + 30 + +
    + + Italy + J Endocrinol Invest + 7806594 + 0391-4097 + title in an other language + 12345 + + + + Koop + C Everett + CE + + + + + + + Psychosom Med. 2008 Jun;70(5):539-45 + 18519880 + + + Psychosom Med. 2008 Jun;70(5):531-8 + 18541904 + + + Lancet. 2002 May 25;359(9320):1851-6 + 12044394 + + + JAMA. 2006 Aug 9;296(6):679-90 + 16896111 + + + Am J Psychiatry. 1988 Aug;145(8):976-81 + 2969199 + + + PLoS Med. 2009 Jan 27;6(1):e11 + 19175285 + + + + amino + other symbol + + 23 + fly + a note + + + 0 + Iodine Radioisotopes + + + Q51BO43MG4 + Thyroxine + + + IM + + + Wood + D L + DL + + Vanderbilt U, Nashville, TN + + + + + keyword + another keyword + + + + Female + + + Graves Disease + radiotherapy + + + Humans + + + Hypothyroidism + etiology + + + Iodine Radioisotopes + adverse effects + therapeutic use + + + Retrospective Studies + + + Thyrotoxicosis + radiotherapy + + + Thyroxine + blood + + + Treatment Failure + + + Weight Gain + + + 14.1 +
    + + + + 2013 + 4 + 30 + + + 2013 + 5 + 2 + 6 + 0 + + + 2013 + 5 + 2 + 6 + 0 + + + 2014 + 7 + 7 + 6 + 0 + + + ppublish + + 8949 + 10.3275/8949 + 23633646 + + +
    + + + 21413195 + + NBK51812 + + + + Royal College of Physicians (UK) + London + + Rheumatoid Arthritis: National Clinical Guideline for Management and Treatment in Adults + + 2009 + 02 + + + + National Collaborating Centre for Chronic Conditions (UK) + + + National Institute for Health and Clinical Excellence: Guidance + 9781860163593 + + eng + Review + Practice Guideline + + just a dummy. + Copyright from somwhere + + +
    + Guideline Development Group members +
    +
    + Acknowledgements +
    +
    + Preface +
    +
    + Acronyms, abbreviations and glossary +
    +
    + Development of the Guideline +
    + 1 + Introduction +
    +
    + 2 + Methodology +
    +
    + 3 + Key messages of the guideline +
    +
    +
    + The Guideline +
    + 4 + Referral, diagnosis and investigations +
    +
    + 5 + Communication and education +
    +
    + 6 + The multidisciplinary team +
    +
    + 7 + Pharmacological management +
    +
    + 8 + Monitoring rheumatoid arthritis +
    +
    + 9 + Other aspects and treatment +
    +
    + 10 + NICE technology appraisal related recommendations +
    +
    + 11 + Areas for future research +
    +
    +
    + References +
    +
    + Appendices +
    +
    + Evidence Tables +
    +
    +
    + + + + 2011 + 3 + 18 + 6 + 0 + + + 2011 + 3 + 18 + 6 + 0 + + + 2011 + 3 + 18 + 6 + 0 + + + ppublish + + 21413195 + + +
    + +
    \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.bib new file mode 100644 index 000000000000..3f3614dcfdb5 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.bib @@ -0,0 +1,15 @@ +@Article{, + title = {Rheumatoid Arthritis: National Clinical Guideline for Management and Treatment in Adults}, + year = {2009}, + month = {02}, + abstract = {just a dummy.}, + author = {National Collaborating Centre for Chronic Conditions (UK) and Williams, Darlisha A}, + copyright = {Copyright from somwhere}, + isbn = {9781860163593}, + pmid = {21413195}, + publisher = {Royal College of Physicians (UK)}, + publocation = {London}, + pubstatus = {ppublish}, + pubtype = {Review, Practice Guideline}, + sections = {Guideline Development Group members; Acknowledgements; Preface; Acronyms, abbreviations and glossary; Development of the Guideline; The Guideline; References; Appendices; Evidence Tables}, +} diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.xml new file mode 100644 index 000000000000..2f866b35245a --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestPubmedBook.xml @@ -0,0 +1,143 @@ + + + 21413195 + + NBK51812 + + + + Royal College of Physicians (UK) + London + + Rheumatoid Arthritis: National Clinical Guideline for Management and Treatment in Adults + + 2009 + 02 + + + + National Collaborating Centre for Chronic Conditions (UK) + + + Williams + Darlisha A + DA + + Division of Infectious Disease and International Health, Department of Medicine, University of Minnesota, Minneapolis, MN, USA; Infectious Disease Institute, Makerere University, Kampala, Uganda. + + + + National Institute for Health and Clinical Excellence: Guidance + 9781860163593 + + eng + Review + Practice Guideline + + just a dummy. + Copyright from somwhere + + +
    + Guideline Development Group members +
    +
    + Acknowledgements +
    +
    + Preface +
    +
    + Acronyms, abbreviations and glossary +
    +
    + Development of the Guideline +
    + 1 + Introduction +
    +
    + 2 + Methodology +
    +
    + 3 + Key messages of the guideline +
    +
    +
    + The Guideline +
    + 4 + Referral, diagnosis and investigations +
    +
    + 5 + Communication and education +
    +
    + 6 + The multidisciplinary team +
    +
    + 7 + Pharmacological management +
    +
    + 8 + Monitoring rheumatoid arthritis +
    +
    + 9 + Other aspects and treatment +
    +
    + 10 + NICE technology appraisal related recommendations +
    +
    + 11 + Areas for future research +
    +
    +
    + References +
    +
    + Appendices +
    +
    + Evidence Tables +
    +
    +
    + + + + 2011 + 3 + 18 + 6 + 0 + + + 2011 + 3 + 18 + 6 + 0 + + + 2011 + 3 + 18 + 6 + 0 + + + ppublish + + 21413195 + + +
    diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib deleted file mode 100644 index d27cd647e68a..000000000000 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.bib +++ /dev/null @@ -1,15 +0,0 @@ -% Encoding: UTF-8 - -@Article{, - Title = {Formate assay in body fluids: application in methanol poisoning.}, - Author = {Makar, A. B. and McMartin, K. E. and Palese, M. and Tephly, T. R.}, - Journal = {Biochem Med}, - Year = {1999}, - Number = {2}, - Pages = {117--126}, - Volume = {13}, - Keywords = {Aldehyde Oxidoreductases, metabolism; Animals; Body Fluids, analysis; Carbon Dioxide, blood; Formates, blood/poisoning; Haplorhini; Humans; Hydrogen-Ion Concentration; Kinetics; Methanol, blood; Methods; Pseudomonas, enzymology}, - Language = {eng}, - Medline-pst = {ppublish}, - Pmid = {1} -} \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml b/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml deleted file mode 100644 index 2a3e6ba030e4..000000000000 --- a/src/test/resources/net/sf/jabref/importer/fileformat/MedlineImporterTestSingleEntry.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - -1 - -1976 -01 -16 - - -1976 -01 -16 - - -2013 -11 -21 - -
    - -0006-2944 - -13 -2 - -1999 Spring - - -Biochemical medicine -Biochem Med - -Formate assay in body fluids: application in methanol poisoning. - -117-26 - - - -Makar -A B -AB - - -McMartin -K E -KE - - -Palese -M -M - - -Tephly -T R -TR - - -eng - -Journal Article -Research Support, U.S. Gov't, P.H.S. - -
    - -UNITED STATES -Biochem Med -0151424 -0006-2944 - - - -0 -Formates - - -142M471B3J -Carbon Dioxide - - -EC 1.2.- -Aldehyde Oxidoreductases - - -Y4S76JWI15 -Methanol - - -IM - - -Aldehyde Oxidoreductases -metabolism - - -Animals - - -Body Fluids -analysis - - -Carbon Dioxide -blood - - -Formates -blood -poisoning - - -Haplorhini - - -Humans - - -Hydrogen-Ion Concentration - - -Kinetics - - -Methanol -blood - - -Methods - - -Pseudomonas -enzymology - - -
    - -ppublish - -1 - - -
    -
    \ No newline at end of file From 4459a72cc739bd9754343db8e9221087b4758eba Mon Sep 17 00:00:00 2001 From: Joerg Lenhard Date: Thu, 21 Jul 2016 13:37:52 +0200 Subject: [PATCH 254/268] Add test in BibEntryWriterTest for type change --- .../logic/bibtex/BibEntryWriterTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java index 15aa1ff65684..764d22695394 100644 --- a/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/bibtex/BibEntryWriterTest.java @@ -191,6 +191,44 @@ public void roundTripWithCamelCasingInTheOriginalEntryAndResultInLowerCase() thr assertEquals(expected, actual); } + @Test + public void testEntryTypeChange() throws IOException { + // @formatter:off + String expected = Globals.NEWLINE + "@Article{test," + Globals.NEWLINE + + " author = {BlaBla}," + Globals.NEWLINE + + " journal = {International Journal of Something}," + Globals.NEWLINE + + " number = {1}," + Globals.NEWLINE + + " note = {some note}," + Globals.NEWLINE + + " howpublished = {asdf}," + Globals.NEWLINE + + "}" + Globals.NEWLINE; + // @formatter:on + + // read in bibtex string + ParserResult result = BibtexParser.parse(new StringReader(expected)); + Collection entries = result.getDatabase().getEntries(); + BibEntry entry = entries.iterator().next(); + + // modify entry + entry.setType("inproceedings"); + + //write out bibtex string + StringWriter stringWriter = new StringWriter(); + writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); + String actual = stringWriter.toString(); + + // @formatter:off + String expectedNewEntry = Globals.NEWLINE + "@InProceedings{test," + Globals.NEWLINE + + " author = {BlaBla}," + Globals.NEWLINE + + " number = {1}," + Globals.NEWLINE + + " note = {some note}," + Globals.NEWLINE + + " howpublished = {asdf}," + Globals.NEWLINE + + " journal = {International Journal of Something}," + Globals.NEWLINE + + "}" + Globals.NEWLINE; + // @formatter:on + assertEquals(expectedNewEntry, actual); + } + + @Test public void roundTripWithAppendedNewlines() throws IOException { // @formatter:off From f30aef36338332c39b97d4356a392f79cb1b2207 Mon Sep 17 00:00:00 2001 From: Braunch Date: Thu, 21 Jul 2016 14:15:01 +0200 Subject: [PATCH 255/268] When clicking on a tab, the first field now has the focus (#988) * the first Field does now have focus when clicking on a tab in the entry editor * Make first field focused when selecting a tab in entry editor --- CHANGELOG.md | 2 +- src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e7e7016d7d..a38b30dd95a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -476,4 +476,4 @@ The changelog of 2.11 and versions before is maintained as [text file](https://g [3.1]: https://github.com/JabRef/jabref/compare/v3.0...v3.1 [3.0]: https://github.com/JabRef/jabref/compare/v2.11.1...v3.0 [dev_2.11]: https://github.com/JabRef/jabref/compare/v2.11.1...dev_2.11 -[2.11.1]: https://github.com/JabRef/jabref/compare/v2.11...v2.11.1 +[2.11.1]: https://github.com/JabRef/jabref/compare/v2.11...v2.11.1 \ No newline at end of file diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index ef51e8324553..fce31985cc19 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -309,7 +309,7 @@ private void setupFieldPanels() { otherFields.remove("bibtexkey"); otherFields.removeAll(Globals.prefs.getCustomTabFieldNames()); - if(!otherFields.isEmpty()) { + if (!otherFields.isEmpty()) { addOtherTab(otherFields); } @@ -1026,6 +1026,7 @@ public void stateChanged(ChangeEvent event) { Object activeTab = tabs.get(tabbed.getSelectedIndex()); if (activeTab instanceof EntryEditorTab) { ((EntryEditorTab) activeTab).updateAll(); + activateVisible(); } }); } @@ -1436,7 +1437,7 @@ private void warnDuplicateBibtexkey() { } private void warnEmptyBibtexkey() { - panel.output(Localization.lang("Empty BibTeX key")+". "+Localization.lang("Grouping may not work for this entry.")); + panel.output(Localization.lang("Empty BibTeX key") + ". " + Localization.lang("Grouping may not work for this entry.")); } From 81baf40adb54f74d081d8540873154111fe80705 Mon Sep 17 00:00:00 2001 From: Braunch Date: Thu, 21 Jul 2016 14:15:35 +0200 Subject: [PATCH 256/268] The field list gets the focus as soon as it is focused (#1541) --- CHANGELOG.md | 1 + .../net/sf/jabref/gui/FieldSetComponent.java | 32 +++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a38b30dd95a1..c38e5bb790b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - [#1249](https://github.com/JabRef/jabref/issues/1249) Date layout formatter added - Added ISBN integrity checker - Added filter to not show selected integrity checks +- Enhance the entry customization dialog to give better visual feedback ### Fixed - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly diff --git a/src/main/java/net/sf/jabref/gui/FieldSetComponent.java b/src/main/java/net/sf/jabref/gui/FieldSetComponent.java index 743de26716cd..992f3e3fd701 100644 --- a/src/main/java/net/sf/jabref/gui/FieldSetComponent.java +++ b/src/main/java/net/sf/jabref/gui/FieldSetComponent.java @@ -22,6 +22,8 @@ import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; @@ -48,7 +50,6 @@ import net.sf.jabref.logic.labelpattern.LabelPatternUtil; /** - * * @author alver */ class FieldSetComponent extends JPanel implements ActionListener { @@ -176,6 +177,8 @@ private FieldSetComponent(String title, List fields, List preset gbl.setConstraints(add, con); add(add); + FieldListFocusListener fieldListFocusListener = new FieldListFocusListener(list); + list.addFocusListener(fieldListFocusListener); } public void setListSelectionMode(int mode) { @@ -191,7 +194,7 @@ public void selectField(String fieldName) { // Make sure it is visible: JViewport viewport = sp.getViewport(); Rectangle rectangle = list.getCellBounds(idx, idx); - if(rectangle != null) { + if (rectangle != null) { viewport.scrollRectToVisible(rectangle); } @@ -364,4 +367,29 @@ public void actionPerformed(ActionEvent e) { } } + /** + * FocusListener to select the first entry in the list of fields when they are focused + */ + protected class FieldListFocusListener implements FocusListener { + + private JList list; + + public FieldListFocusListener(JList list) { + this.list = list; + } + + @Override + public void focusGained(FocusEvent e) { + if (list.getSelectedValue() == null) { + list.setSelectedIndex(0); + } + } + + @Override + public void focusLost(FocusEvent e) { + //focus should remain at the same position so nothing to do here + } + } + + } From 5eabc42373792641e151acb6944c3d1d7f5fc3c9 Mon Sep 17 00:00:00 2001 From: Sascha Zeller Date: Thu, 21 Jul 2016 14:24:35 +0200 Subject: [PATCH 257/268] Test CustomImporter (#1501) * Test CustomImporter --- .../sf/jabref/importer/CustomImporter.java | 13 +- .../jabref/importer/CustomImporterTest.java | 136 ++++++++++++++++++ 2 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 src/test/java/net/sf/jabref/importer/CustomImporterTest.java diff --git a/src/main/java/net/sf/jabref/importer/CustomImporter.java b/src/main/java/net/sf/jabref/importer/CustomImporter.java index e46687702160..b74a6756e7d2 100644 --- a/src/main/java/net/sf/jabref/importer/CustomImporter.java +++ b/src/main/java/net/sf/jabref/importer/CustomImporter.java @@ -60,13 +60,17 @@ public CustomImporter(List data) { } public CustomImporter(String name, String cliId, String className, String basePath) { - super(); + this(); this.name = name; this.cliId = cliId; this.className = className; this.basePath = basePath; } + public CustomImporter(ImportFormat importer) { + this(importer.getFormatName(), importer.getId(), importer.getClass().getName(), "src/main/java/net/sf/jabref/importer/fileformat/" + importer.getFormatName() + "Importer.java"); + } + public String getName() { return this.name; } @@ -113,7 +117,12 @@ public List getAsStringList() { @Override public boolean equals(Object o) { - return (o instanceof CustomImporter) && this.getName().equals(((CustomImporter) o).getName()); + boolean equalName = this.getName().equals(((CustomImporter) o).getName()); + boolean equalCliId = this.getClidId().equals(((CustomImporter) o).getClidId()); + boolean equalClassName = this.getClassName().equals(((CustomImporter) o).getClassName()); + boolean equalBasePath = this.getBasePath().equals(((CustomImporter) o).getBasePath()); + + return (o instanceof CustomImporter) && equalName && equalCliId && equalClassName && equalBasePath; } @Override diff --git a/src/test/java/net/sf/jabref/importer/CustomImporterTest.java b/src/test/java/net/sf/jabref/importer/CustomImporterTest.java new file mode 100644 index 000000000000..478817d7f3d4 --- /dev/null +++ b/src/test/java/net/sf/jabref/importer/CustomImporterTest.java @@ -0,0 +1,136 @@ +package net.sf.jabref.importer; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.importer.fileformat.BibTeXMLImporter; +import net.sf.jabref.importer.fileformat.CopacImporter; +import net.sf.jabref.importer.fileformat.OvidImporter; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +public class CustomImporterTest { + + private CustomImporter importer; + + @Before + public void setUp() { + Globals.prefs = JabRefPreferences.getInstance(); + importer = new CustomImporter(new CopacImporter()); + } + + @Test + public void testGetName() { + assertEquals("Copac", importer.getName()); + } + + @Test + public void testGetCliId() { + assertEquals("cpc", importer.getClidId()); + } + + @Test + public void testGetClassName() { + assertEquals("net.sf.jabref.importer.fileformat.CopacImporter", importer.getClassName()); + } + + @Test + public void testGetBasePath() { + assertEquals("src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java", importer.getBasePath()); + } + + @Test + public void testGetInstance() throws Exception { + assertEquals(new CopacImporter(), importer.getInstance()); + } + + @Test + public void testGetFileFromBasePath() { + assertEquals(new File("src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java"), importer.getFileFromBasePath()); + } + + @Test + public void testGetBasePathUrl() throws Exception { + assertEquals(new File("src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java").toURI().toURL(), importer.getBasePathUrl()); + } + + @Test + public void testGetAsStringList() { + assertEquals("Copac", importer.getAsStringList().get(0)); + assertEquals("cpc", importer.getAsStringList().get(1)); + assertEquals("net.sf.jabref.importer.fileformat.CopacImporter", importer.getAsStringList().get(2)); + assertEquals("src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java", importer.getAsStringList().get(3)); + } + + @Test + public void testEqualsTrue() { + assertEquals(importer, importer); + } + + @Test + public void testEqualsFalse() { + assertNotEquals(new CopacImporter(), importer); + } + + @Test + public void testCompareToSmaller() { + CustomImporter ovidImporter = new CustomImporter(new OvidImporter()); + + assertTrue(importer.compareTo(ovidImporter) < 0); + } + + @Test + public void testCompareToGreater() { + CustomImporter bibtexmlImporter = new CustomImporter(new BibTeXMLImporter()); + CustomImporter ovidImporter = new CustomImporter(new OvidImporter()); + + assertTrue(ovidImporter.compareTo(bibtexmlImporter) > 0); + } + + @Test + public void testCompareToEven() { + assertEquals(0, importer.compareTo(importer)); + } + + @Test + public void testToString() { + assertEquals("Copac", importer.toString()); + } + + @Test + public void testClassicConstructor() { + CustomImporter customImporter = new CustomImporter("Copac", "cpc", "net.sf.jabref.importer.fileformat.CopacImporter", "src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java"); + + assertEquals(importer, customImporter); + } + + @Test + public void testListConstructor() { + List dataTest = Arrays.asList("Ovid", "ovid", "net.sf.jabref.importer.fileformat.OvidImporter", "src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java"); + CustomImporter customImporter = new CustomImporter(dataTest); + CustomImporter customOvidImporter = new CustomImporter(new OvidImporter()); + + assertEquals(customImporter, customOvidImporter); + } + + @Test + public void testEmptyConstructor() { + CustomImporter customImporter = new CustomImporter(); + customImporter.setName("Ovid"); + customImporter.setCliId("ovid"); + customImporter.setClassName("net.sf.jabref.importer.fileformat.OvidImporter"); + customImporter.setBasePath("src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java"); + + CustomImporter customOvidImporter = new CustomImporter(new OvidImporter()); + + assertEquals(customImporter, customOvidImporter); + } +} From f1ff5ce7e10b1d9e89067f8c35f73bdb0653b9f9 Mon Sep 17 00:00:00 2001 From: Simon Harrer Date: Thu, 21 Jul 2016 14:48:51 +0200 Subject: [PATCH 258/268] Fixes imports --- src/test/java/net/sf/jabref/importer/CustomImporterTest.java | 2 +- .../net/sf/jabref/importer/fileformat/CopacImporterTest.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/net/sf/jabref/importer/CustomImporterTest.java b/src/test/java/net/sf/jabref/importer/CustomImporterTest.java index 478817d7f3d4..fac5fb75ab8f 100644 --- a/src/test/java/net/sf/jabref/importer/CustomImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/CustomImporterTest.java @@ -5,10 +5,10 @@ import java.util.List; import net.sf.jabref.Globals; -import net.sf.jabref.JabRefPreferences; import net.sf.jabref.importer.fileformat.BibTeXMLImporter; import net.sf.jabref.importer.fileformat.CopacImporter; import net.sf.jabref.importer.fileformat.OvidImporter; +import net.sf.jabref.preferences.JabRefPreferences; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java index f04544b6c71d..02d316cf1f21 100644 --- a/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java +++ b/src/test/java/net/sf/jabref/importer/fileformat/CopacImporterTest.java @@ -27,6 +27,7 @@ public class CopacImporterTest { /** * Generates a List of all files in the package "/src/test/resources/net/sf/jabref/importer/fileformat" + * * @return A list of Names * @throws IOException */ From 32319fff33a20e21276dd02124cb81df8e9174f8 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Thu, 21 Jul 2016 15:01:05 +0200 Subject: [PATCH 259/268] Added model.entry.FieldName that contains field name constants (#1602) * Added model.entry.FieldName that contains field name constants * More constants * Renamed and added more constants * Some more fields and cleanups * Removed MedlineHandler left from merge conflicts --- .../net/sf/jabref/BibDatabaseContext.java | 3 +- src/main/java/net/sf/jabref/Globals.java | 2 - src/main/java/net/sf/jabref/MetaData.java | 13 +- .../net/sf/jabref/collab/ChangeScanner.java | 3 +- .../sf/jabref/external/AttachFileAction.java | 10 +- .../net/sf/jabref/external/AutoSetLinks.java | 7 +- .../jabref/external/DroppedFileHandler.java | 7 +- .../jabref/external/FindFullTextAction.java | 10 +- .../jabref/external/SynchronizeFileField.java | 11 +- .../TransferableFileLinkSelection.java | 4 +- .../sf/jabref/external/WriteXMPAction.java | 5 +- .../external/WriteXMPEntryEditorAction.java | 6 +- .../java/net/sf/jabref/gui/BasePanel.java | 21 +- .../sf/jabref/gui/ContentSelectorDialog2.java | 9 +- .../java/net/sf/jabref/gui/GUIGlobals.java | 9 +- .../sf/jabref/gui/ImportInspectionDialog.java | 33 +-- .../java/net/sf/jabref/gui/PreviewPanel.java | 3 +- .../gui/actions/ManageKeywordsAction.java | 5 +- .../gui/cleanup/CleanupPresetPanel.java | 3 +- .../sf/jabref/gui/desktop/JabRefDesktop.java | 15 +- .../jabref/gui/entryeditor/EntryEditor.java | 7 +- .../gui/entryeditor/FieldExtraComponents.java | 3 +- .../gui/fieldeditors/FieldNameLabel.java | 9 +- .../sf/jabref/gui/groups/AutoGroupDialog.java | 9 +- .../net/sf/jabref/gui/groups/GroupDialog.java | 3 +- .../gui/groups/WarnAssignmentSideEffects.java | 3 +- .../jabref/gui/journals/AbbreviateAction.java | 5 +- .../gui/journals/UnabbreviateAction.java | 5 +- .../sf/jabref/gui/maintable/MainTable.java | 3 +- .../jabref/gui/maintable/MainTableFormat.java | 5 +- .../maintable/MainTableSelectionListener.java | 9 +- .../maintable/SpecialMainTableColumns.java | 12 +- .../sf/jabref/gui/menus/RightClickMenu.java | 13 +- .../gui/mergeentries/MergeEntryDOIDialog.java | 3 +- .../sf/jabref/gui/openoffice/OOBibBase.java | 9 +- .../gui/openoffice/StyleSelectDialog.java | 15 +- .../gui/openoffice/UndefinedBibtexEntry.java | 3 +- .../gui/plaintextimport/TextInputDialog.java | 3 +- .../net/sf/jabref/gui/preftabs/FileTab.java | 5 +- .../jabref/gui/preftabs/PreviewPrefsTab.java | 23 +- .../gui/search/SearchResultsDialog.java | 27 +- .../jabref/importer/DatabaseFileLookup.java | 4 +- .../jabref/importer/EntryFromFileCreator.java | 10 +- .../jabref/importer/EntryFromPDFCreator.java | 7 +- .../net/sf/jabref/importer/OAI2Handler.java | 27 +- .../importer/fetcher/ACMPortalFetcher.java | 11 +- .../jabref/importer/fetcher/ADSFetcher.java | 5 +- .../importer/fetcher/CiteSeerXFetcher.java | 9 +- .../sf/jabref/importer/fetcher/CrossRef.java | 11 +- .../fetcher/CrossrefFetcherEvaluator.java | 3 +- .../importer/fetcher/DOItoBibTeXFetcher.java | 5 +- .../importer/fetcher/DiVAtoBibTeXFetcher.java | 5 +- .../sf/jabref/importer/fetcher/GVKParser.java | 27 +- .../fetcher/GoogleScholarFetcher.java | 9 +- .../importer/fetcher/IEEEXploreFetcher.java | 57 ++-- .../importer/fetcher/ISBNtoBibTeXFetcher.java | 5 +- .../jabref/importer/fetcher/OAI2Fetcher.java | 5 +- .../fileformat/BiblioscapeImporter.java | 29 +- .../importer/fileformat/BibtexParser.java | 3 +- .../importer/fileformat/CopacImporter.java | 13 +- .../importer/fileformat/EndnoteImporter.java | 35 +-- .../importer/fileformat/FreeCiteImporter.java | 21 +- .../importer/fileformat/InspecImporter.java | 19 +- .../importer/fileformat/IsiImporter.java | 35 +-- .../importer/fileformat/JSONEntryParser.java | 49 ++-- .../fileformat/MedlinePlainImporter.java | 45 ++-- .../importer/fileformat/OvidImporter.java | 77 +++--- .../fileformat/PdfContentImporter.java | 25 +- .../importer/fileformat/RepecNepImporter.java | 13 +- .../importer/fileformat/RisImporter.java | 49 ++-- .../fileformat/SilverPlatterImporter.java | 31 +-- .../net/sf/jabref/logic/TypedBibEntry.java | 10 +- .../autocompleter/AutoCompleterFactory.java | 7 +- .../sf/jabref/logic/auxparser/AuxParser.java | 3 +- .../jabref/logic/bibtex/BibEntryWriter.java | 2 +- .../logic/bibtex/FieldContentParser.java | 5 +- .../comparator/CrossRefEntryComparator.java | 8 +- .../bibtex/comparator/FieldComparator.java | 5 +- src/main/java/net/sf/jabref/logic/bst/VM.java | 5 +- .../jabref/logic/cleanup/BiblatexCleanup.java | 21 +- .../sf/jabref/logic/cleanup/DoiCleanup.java | 17 +- .../logic/cleanup/FileLinksCleanup.java | 8 +- .../cleanup/UpgradePdfPsToFileCleanup.java | 8 +- .../exporter/FieldFormatterCleanups.java | 9 +- .../jabref/logic/exporter/OOCalcDatabase.java | 29 +- .../exporter/OpenDocumentRepresentation.java | 29 +- .../net/sf/jabref/logic/fulltext/ACS.java | 3 +- .../net/sf/jabref/logic/fulltext/ArXiv.java | 3 +- .../jabref/logic/fulltext/DoiResolution.java | 3 +- .../jabref/logic/fulltext/FindFullText.java | 5 +- .../jabref/logic/fulltext/GoogleScholar.java | 5 +- .../net/sf/jabref/logic/fulltext/IEEE.java | 5 +- .../jabref/logic/fulltext/ScienceDirect.java | 3 +- .../jabref/logic/fulltext/SpringerLink.java | 3 +- .../jabref/logic/integrity/ISBNChecker.java | 9 +- .../jabref/logic/integrity/ISSNChecker.java | 9 +- .../logic/integrity/IntegrityCheck.java | 36 +-- .../logic/labelpattern/LabelPatternUtil.java | 39 +-- .../layout/format/CreateDocBookAuthors.java | 3 +- .../layout/format/CreateDocBookEditors.java | 3 +- .../jabref/logic/layout/format/FileLink.java | 3 +- .../logic/layout/format/WrapFileLinks.java | 3 +- .../net/sf/jabref/logic/mods/MODSEntry.java | 39 +-- .../jabref/logic/msbib/BibTeXConverter.java | 15 +- .../sf/jabref/logic/msbib/MSBibConverter.java | 41 +-- .../sf/jabref/logic/msbib/MSBibMapping.java | 27 +- .../jabref/logic/openoffice/OOBibStyle.java | 3 +- .../net/sf/jabref/logic/util/io/FileUtil.java | 4 +- .../sf/jabref/logic/xmp/XMPSchemaBibtex.java | 5 +- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 59 +++-- .../migrations/FileLinksUpgradeWarning.java | 9 +- .../migrations/PreferencesMigrations.java | 17 +- .../net/sf/jabref/model/DuplicateCheck.java | 13 +- .../sf/jabref/model/database/BibDatabase.java | 3 +- .../net/sf/jabref/model/entry/BibEntry.java | 33 ++- .../model/entry/BibLatexEntryTypes.java | 248 +++++++++--------- .../jabref/model/entry/BibtexEntryTypes.java | 60 ++--- .../sf/jabref/model/entry/EntryConverter.java | 4 +- .../net/sf/jabref/model/entry/EntryUtil.java | 2 +- .../net/sf/jabref/model/entry/FieldName.java | 31 +++ .../model/entry/IEEETranEntryTypes.java | 20 +- .../model/entry/InternalBibtexFields.java | 40 +-- .../net/sf/jabref/pdfimport/PdfImporter.java | 3 +- .../jabref/preferences/JabRefPreferences.java | 36 +-- .../SpecialFieldUpdateListener.java | 3 +- .../specialfields/SpecialFieldsUtils.java | 4 +- .../sf/jabref/model/entry/EntryUtilTest.java | 2 +- 127 files changed, 1072 insertions(+), 947 deletions(-) create mode 100644 src/main/java/net/sf/jabref/model/entry/FieldName.java diff --git a/src/main/java/net/sf/jabref/BibDatabaseContext.java b/src/main/java/net/sf/jabref/BibDatabaseContext.java index 6f95ff4f1d89..c3a381950642 100644 --- a/src/main/java/net/sf/jabref/BibDatabaseContext.java +++ b/src/main/java/net/sf/jabref/BibDatabaseContext.java @@ -9,6 +9,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.database.BibDatabaseModeDetection; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; /** @@ -177,6 +178,6 @@ private String getFileDirectoryPath(String directoryName) { } public List getFileDirectory() { - return getFileDirectory(Globals.FILE_FIELD); + return getFileDirectory(FieldName.FILE); } } diff --git a/src/main/java/net/sf/jabref/Globals.java b/src/main/java/net/sf/jabref/Globals.java index df3c3cfd94c6..c7918627a94d 100644 --- a/src/main/java/net/sf/jabref/Globals.java +++ b/src/main/java/net/sf/jabref/Globals.java @@ -31,8 +31,6 @@ public class Globals { - public static final String FILE_FIELD = "file"; - public static final String FOLDER_FIELD = "folder"; public static final String DIR_SUFFIX = "Directory"; // JabRef version info diff --git a/src/main/java/net/sf/jabref/MetaData.java b/src/main/java/net/sf/jabref/MetaData.java index 1a6369da8e5c..5321bc0c95b1 100644 --- a/src/main/java/net/sf/jabref/MetaData.java +++ b/src/main/java/net/sf/jabref/MetaData.java @@ -40,6 +40,7 @@ import net.sf.jabref.logic.labelpattern.DatabaseLabelPattern; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.sql.DBStrings; import org.apache.commons.logging.Log; @@ -57,7 +58,7 @@ public class MetaData implements Iterable { private static final String DATABASE_TYPE = "databaseType"; private static final String GROUPSTREE = "groupstree"; - private static final String FILE_DIRECTORY = Globals.FILE_FIELD + Globals.DIR_SUFFIX; + private static final String FILE_DIRECTORY = FieldName.FILE + Globals.DIR_SUFFIX; public static final String SELECTOR_META_PREFIX = "selector_"; private static final String PROTECTED_FLAG_META = "protectedFlag"; @@ -126,11 +127,11 @@ public Optional getSaveOrderConfig() { * Add default metadata for new database: */ public void initializeNewDatabase() { - metaData.put(SELECTOR_META_PREFIX + "keywords", new Vector<>()); - metaData.put(SELECTOR_META_PREFIX + "author", new Vector<>()); - metaData.put(SELECTOR_META_PREFIX + "journal", new Vector<>()); - metaData.put(SELECTOR_META_PREFIX + "publisher", new Vector<>()); - metaData.put(SELECTOR_META_PREFIX + "review", new Vector<>()); + metaData.put(SELECTOR_META_PREFIX + FieldName.KEYWORDS, new Vector<>()); + metaData.put(SELECTOR_META_PREFIX + FieldName.AUTHOR, new Vector<>()); + metaData.put(SELECTOR_META_PREFIX + FieldName.JOURNAL, new Vector<>()); + metaData.put(SELECTOR_META_PREFIX + FieldName.PUBLISHER, new Vector<>()); + metaData.put(SELECTOR_META_PREFIX + FieldName.REVIEW, new Vector<>()); } /** diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index ab9987a9a42a..87cd4fea27f7 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -53,6 +53,7 @@ import net.sf.jabref.model.database.EntrySorter; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -60,7 +61,7 @@ public class ChangeScanner implements Runnable { - private static final String[] SORT_BY = new String[] {"year", "author", "title"}; + private static final String[] SORT_BY = new String[] {FieldName.YEAR, FieldName.AUTHOR, FieldName.TITLE}; private final File f; diff --git a/src/main/java/net/sf/jabref/external/AttachFileAction.java b/src/main/java/net/sf/jabref/external/AttachFileAction.java index c81681396600..8429df582212 100644 --- a/src/main/java/net/sf/jabref/external/AttachFileAction.java +++ b/src/main/java/net/sf/jabref/external/AttachFileAction.java @@ -1,6 +1,5 @@ package net.sf.jabref.external; -import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.FileListEntryEditor; @@ -9,6 +8,7 @@ import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Created by IntelliJ IDEA. @@ -39,13 +39,13 @@ public void action() { editor.setVisible(true, true); if (editor.okPressed()) { FileListTableModel model = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(model::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(model::setContent); model.addEntry(model.getRowCount(), flEntry); String newVal = model.getStringRepresentation(); - UndoableFieldChange ce = new UndoableFieldChange(entry, Globals.FILE_FIELD, - entry.getFieldOptional(Globals.FILE_FIELD).orElse(null), newVal); - entry.setField(Globals.FILE_FIELD, newVal); + UndoableFieldChange ce = new UndoableFieldChange(entry, FieldName.FILE, + entry.getFieldOptional(FieldName.FILE).orElse(null), newVal); + entry.setField(FieldName.FILE, newVal); panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); } diff --git a/src/main/java/net/sf/jabref/external/AutoSetLinks.java b/src/main/java/net/sf/jabref/external/AutoSetLinks.java index 41968bced887..64848c282fa8 100644 --- a/src/main/java/net/sf/jabref/external/AutoSetLinks.java +++ b/src/main/java/net/sf/jabref/external/AutoSetLinks.java @@ -29,6 +29,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; public class AutoSetLinks { @@ -111,7 +112,7 @@ public void run() { // Iterate over the entries: for (Entry> entryFilePair : result.entrySet()) { FileListTableModel tableModel; - Optional oldVal = entryFilePair.getKey().getFieldOptional(Globals.FILE_FIELD); + Optional oldVal = entryFilePair.getKey().getFieldOptional(FieldName.FILE); if (singleTableModel == null) { tableModel = new FileListTableModel(); oldVal.ifPresent(tableModel::setContent); @@ -152,12 +153,12 @@ public void run() { if (ce != null) { // store undo information UndoableFieldChange change = new UndoableFieldChange(entryFilePair.getKey(), - Globals.FILE_FIELD, oldVal.orElse(null), newVal); + FieldName.FILE, oldVal.orElse(null), newVal); ce.addEdit(change); } // hack: if table model is given, do NOT modify entry if (singleTableModel == null) { - entryFilePair.getKey().setField(Globals.FILE_FIELD, newVal); + entryFilePair.getKey().setField(FieldName.FILE, newVal); } if (changedEntries != null) { changedEntries.add(entryFilePair.getKey()); diff --git a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java index 351eba391c59..0479631d917b 100644 --- a/src/main/java/net/sf/jabref/external/DroppedFileHandler.java +++ b/src/main/java/net/sf/jabref/external/DroppedFileHandler.java @@ -44,6 +44,7 @@ import net.sf.jabref.logic.xmp.XMPUtil; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import com.jgoodies.forms.builder.FormBuilder; @@ -395,7 +396,7 @@ private boolean showLinkMoveCopyRenameDialog(String linkFileName, ExternalFileTy private void doLink(BibEntry entry, ExternalFileType fileType, String filename, boolean avoidDuplicate, NamedCompound edits) { - Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + Optional oldValue = entry.getFieldOptional(FieldName.FILE); FileListTableModel tm = new FileListTableModel(); oldValue.ifPresent(tm::setContent); @@ -441,8 +442,8 @@ private void doLink(BibEntry entry, ExternalFileType fileType, String filename, tm.addEntry(tm.getRowCount(), new FileListEntry("", filename, fileType)); String newValue = tm.getStringRepresentation(); - UndoableFieldChange edit = new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue.orElse(null), newValue); - entry.setField(Globals.FILE_FIELD, newValue); + UndoableFieldChange edit = new UndoableFieldChange(entry, FieldName.FILE, oldValue.orElse(null), newValue); + entry.setField(FieldName.FILE, newValue); if (edits == null) { panel.getUndoManager().addEdit(edit); diff --git a/src/main/java/net/sf/jabref/external/FindFullTextAction.java b/src/main/java/net/sf/jabref/external/FindFullTextAction.java index d0ce54094dc6..f48c440de456 100644 --- a/src/main/java/net/sf/jabref/external/FindFullTextAction.java +++ b/src/main/java/net/sf/jabref/external/FindFullTextAction.java @@ -22,7 +22,6 @@ import javax.swing.JOptionPane; -import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.undo.UndoableFieldChange; @@ -30,6 +29,7 @@ import net.sf.jabref.logic.fulltext.FindFullText; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -80,12 +80,12 @@ public void update() { try { def.download(result.get(), file -> { FileListTableModel tm = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(tm::setContent); tm.addEntry(tm.getRowCount(), file); String newValue = tm.getStringRepresentation(); - UndoableFieldChange edit = new UndoableFieldChange(entry, Globals.FILE_FIELD, - entry.getFieldOptional(Globals.FILE_FIELD).orElse(null), newValue); - entry.setField(Globals.FILE_FIELD, newValue); + UndoableFieldChange edit = new UndoableFieldChange(entry, FieldName.FILE, + entry.getFieldOptional(FieldName.FILE).orElse(null), newValue); + entry.setField(FieldName.FILE, newValue); basePanel.getUndoManager().addEdit(edit); basePanel.markBaseChanged(); }); diff --git a/src/main/java/net/sf/jabref/external/SynchronizeFileField.java b/src/main/java/net/sf/jabref/external/SynchronizeFileField.java index 4fb72cd7c838..0a798fb1ab29 100644 --- a/src/main/java/net/sf/jabref/external/SynchronizeFileField.java +++ b/src/main/java/net/sf/jabref/external/SynchronizeFileField.java @@ -59,6 +59,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.FormBuilder; @@ -144,7 +145,7 @@ public void run() { boolean removeAllBroken = false; mainLoop: for (BibEntry aSel : sel) { panel.frame().setProgressBarValue(progress++); - final Optional old = aSel.getFieldOptional(Globals.FILE_FIELD); + final Optional old = aSel.getFieldOptional(FieldName.FILE); // Check if a extension is set: if (old.isPresent() && !(old.get().isEmpty())) { FileListTableModel tableModel = new FileListTableModel(); @@ -254,11 +255,11 @@ public void run() { // The table has been modified. Store the change: String toSet = tableModel.getStringRepresentation(); if (toSet.isEmpty()) { - ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old.orElse(null), null)); - aSel.clearField(Globals.FILE_FIELD); + ce.addEdit(new UndoableFieldChange(aSel, FieldName.FILE, old.orElse(null), null)); + aSel.clearField(FieldName.FILE); } else { - ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old.orElse(null), toSet)); - aSel.setField(Globals.FILE_FIELD, toSet); + ce.addEdit(new UndoableFieldChange(aSel, FieldName.FILE, old.orElse(null), toSet)); + aSel.setField(FieldName.FILE, toSet); } changedEntries.add(aSel); } diff --git a/src/main/java/net/sf/jabref/external/TransferableFileLinkSelection.java b/src/main/java/net/sf/jabref/external/TransferableFileLinkSelection.java index a96a56d5b28a..b78d327c9d63 100644 --- a/src/main/java/net/sf/jabref/external/TransferableFileLinkSelection.java +++ b/src/main/java/net/sf/jabref/external/TransferableFileLinkSelection.java @@ -23,11 +23,11 @@ import java.util.ArrayList; import java.util.List; -import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -44,7 +44,7 @@ public class TransferableFileLinkSelection implements Transferable { public TransferableFileLinkSelection(BasePanel panel, List selection) { FileListTableModel tm = new FileListTableModel(); - selection.get(0).getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); + selection.get(0).getFieldOptional(FieldName.FILE).ifPresent(tm::setContent); if (tm.getRowCount() > 0) { // Find the default directory for this field type, if any: List dirs = panel.getBibDatabaseContext().getFileDirectory(); diff --git a/src/main/java/net/sf/jabref/external/WriteXMPAction.java b/src/main/java/net/sf/jabref/external/WriteXMPAction.java index 8864b53e3cec..d69fb185fe09 100644 --- a/src/main/java/net/sf/jabref/external/WriteXMPAction.java +++ b/src/main/java/net/sf/jabref/external/WriteXMPAction.java @@ -49,6 +49,7 @@ import net.sf.jabref.logic.xmp.XMPUtil; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import com.jgoodies.forms.builder.ButtonBarBuilder; @@ -138,9 +139,9 @@ public void run() { .ifPresent(files::add)); // Then check the "file" field: List dirs = panel.getBibDatabaseContext().getFileDirectory(); - if (entry.hasField(Globals.FILE_FIELD)) { + if (entry.hasField(FieldName.FILE)) { FileListTableModel tm = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(tm::setContent); for (int j = 0; j < tm.getRowCount(); j++) { FileListEntry flEntry = tm.getEntry(j); if ((flEntry.type.isPresent()) && "pdf".equalsIgnoreCase(flEntry.type.get().getName())) { diff --git a/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java b/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java index feca27d8c9ee..d4366c247066 100644 --- a/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java +++ b/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java @@ -25,7 +25,6 @@ import javax.swing.Action; import javax.xml.transform.TransformerException; -import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.FileListTableModel; @@ -36,6 +35,7 @@ import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.logic.xmp.XMPUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Write XMP action for EntryEditor toolbar. @@ -73,9 +73,9 @@ public void actionPerformed(ActionEvent actionEvent) { // Then check the "file" field: List dirs = panel.getBibDatabaseContext().getFileDirectory(); - if (entry.hasField(Globals.FILE_FIELD)) { + if (entry.hasField(FieldName.FILE)) { FileListTableModel tm = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(tm::setContent); for (int j = 0; j < tm.getRowCount(); j++) { FileListEntry flEntry = tm.getEntry(j); if ((flEntry.type.isPresent()) && "pdf".equalsIgnoreCase(flEntry.type.get().getName())) { diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 8e0f54bfafff..9e8e4c8839a4 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -126,6 +126,7 @@ import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.event.EntryAddedEvent; import net.sf.jabref.model.event.EntryChangedEvent; @@ -1034,13 +1035,13 @@ private void openExternalFile() { } final BibEntry entry = bes.get(0); - if (!entry.hasField(Globals.FILE_FIELD)) { + if (!entry.hasField(FieldName.FILE)) { // no bibtex field new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); return; } FileListTableModel tableModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tableModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(tableModel::setContent); if (tableModel.getRowCount() == 0) { // content in bibtex field is not readable new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); @@ -2055,8 +2056,6 @@ public void action() { private class OpenURLAction implements BaseAction { - private static final String URL_FIELD = "url"; - private static final String DOI_FIELD = "doi"; private static final String PS_FIELD = "ps"; private static final String PDF_FIELD = "pdf"; @@ -2065,11 +2064,11 @@ private class OpenURLAction implements BaseAction { public void action() { final List bes = mainTable.getSelectedEntries(); if (bes.size() == 1) { - String field = DOI_FIELD; - Optional link = bes.get(0).getFieldOptional(DOI_FIELD); - if (bes.get(0).hasField(URL_FIELD)) { - link = bes.get(0).getFieldOptional(URL_FIELD); - field = URL_FIELD; + String field = FieldName.DOI; + Optional link = bes.get(0).getFieldOptional(FieldName.DOI); + if (bes.get(0).hasField(FieldName.URL)) { + link = bes.get(0).getFieldOptional(FieldName.URL); + field = FieldName.URL; } if (link.isPresent()) { try { @@ -2083,10 +2082,10 @@ public void action() { // Look for web links in the "file" field as a fallback: FileListEntry entry = null; FileListTableModel tm = new FileListTableModel(); - bes.get(0).getFieldOptional(Globals.FILE_FIELD).ifPresent(tm::setContent); + bes.get(0).getFieldOptional(FieldName.FILE).ifPresent(tm::setContent); for (int i = 0; i < tm.getRowCount(); i++) { FileListEntry flEntry = tm.getEntry(i); - if (URL_FIELD.equalsIgnoreCase(flEntry.type.get().getName()) + if (FieldName.URL.equalsIgnoreCase(flEntry.type.get().getName()) || PS_FIELD.equalsIgnoreCase(flEntry.type.get().getName()) || PDF_FIELD.equalsIgnoreCase(flEntry.type.get().getName())) { entry = flEntry; diff --git a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java index 8dcf101b1c02..282d1fbe1b65 100644 --- a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java +++ b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java @@ -48,6 +48,7 @@ import net.sf.jabref.gui.keyboard.KeyBinder; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.FieldName; import com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.logging.Log; @@ -320,10 +321,10 @@ private void setupFieldSelector() { } if (contents.isEmpty()) { // if nothing was added, put the default fields (as described in the help) - fieldListModel.addElement("author"); - fieldListModel.addElement("journal"); - fieldListModel.addElement("keywords"); - fieldListModel.addElement("publisher"); + fieldListModel.addElement(FieldName.AUTHOR); + fieldListModel.addElement(FieldName.JOURNAL); + fieldListModel.addElement(FieldName.KEYWORDS); + fieldListModel.addElement(FieldName.PUBLISHER); } else { for (String s : contents) { fieldListModel.addElement(s); diff --git a/src/main/java/net/sf/jabref/gui/GUIGlobals.java b/src/main/java/net/sf/jabref/gui/GUIGlobals.java index f5a5e38b2169..8f1ed9552bcb 100644 --- a/src/main/java/net/sf/jabref/gui/GUIGlobals.java +++ b/src/main/java/net/sf/jabref/gui/GUIGlobals.java @@ -27,6 +27,7 @@ import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.gui.keyboard.EmacsKeyBindings; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; @@ -100,7 +101,7 @@ public static void init() { label = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " URL"); - GUIGlobals.TABLE_ICONS.put("url", label); + GUIGlobals.TABLE_ICONS.put(FieldName.URL, label); label = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " CiteSeer URL"); @@ -112,7 +113,7 @@ public static void init() { label = new JLabel(IconTheme.JabRefIcon.DOI.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " DOI " + Localization.lang("web link")); - GUIGlobals.TABLE_ICONS.put("doi", label); + GUIGlobals.TABLE_ICONS.put(FieldName.DOI, label); label = new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " PS"); @@ -120,11 +121,11 @@ public static void init() { label = new JLabel(IconTheme.JabRefIcon.FOLDER.getSmallIcon()); label.setToolTipText(Localization.lang("Open folder")); - GUIGlobals.TABLE_ICONS.put(Globals.FOLDER_FIELD, label); + GUIGlobals.TABLE_ICONS.put(FieldName.FOLDER, label); label = new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon()); label.setToolTipText(Localization.lang("Open file")); - GUIGlobals.TABLE_ICONS.put(Globals.FILE_FIELD, label); + GUIGlobals.TABLE_ICONS.put(FieldName.FILE, label); for (ExternalFileType fileType : ExternalFileTypes.getInstance().getExternalFileTypeSelection()) { label = new JLabel(fileType.getIcon()); diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 61323de91345..4e09e52a7db9 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -99,6 +99,7 @@ import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -178,12 +179,12 @@ public class ImportInspectionDialog extends JDialog implements ImportInspector, private final JLabel duplLabel = new JLabel(IconTheme.JabRefIcon.DUPLICATE.getSmallIcon()); private final JLabel fileLabel = new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon()); private final JLabel urlLabel = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); - private static final List INSPECTION_FIELDS = Arrays.asList("author", "title", "year", BibEntry.KEY_FIELD); + private static final List INSPECTION_FIELDS = Arrays.asList(FieldName.AUTHOR, FieldName.TITLE, FieldName.YEAR, BibEntry.KEY_FIELD); private static final int DUPL_COL = 1; private static final int FILE_COL = 2; private static final int URL_COL = 3; private static final int PAD = 4; - private static final String URL_FIELD = "url"; + private static final String URL_FIELD = FieldName.URL; /** @@ -905,9 +906,9 @@ public void mouseClicked(MouseEvent e) { BibEntry entry = sortedList.get(row); if (col == FILE_COL) { - if (entry.hasField(Globals.FILE_FIELD)) { + if (entry.hasField(FieldName.FILE)) { FileListTableModel tableModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tableModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(tableModel::setContent); if (tableModel.getRowCount() == 0) { return; } @@ -962,7 +963,7 @@ private void showFileFieldMenu(MouseEvent e) { JPopupMenu menu = new JPopupMenu(); int count = 0; FileListTableModel fileList = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileList::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(fileList::setContent); // If there are one or more links, open the first one: for (int i = 0; i < fileList.getRowCount(); i++) { FileListEntry flEntry = fileList.getEntry(i); @@ -1184,11 +1185,11 @@ public void actionPerformed(ActionEvent actionEvent) { public void downloadComplete(FileListEntry file) { ImportInspectionDialog.this.toFront(); // Hack FileListTableModel localModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(localModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(localModel::setContent); localModel.addEntry(localModel.getRowCount(), file); entries.getReadWriteLock().writeLock().lock(); try { - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + entry.setField(FieldName.FILE, localModel.getStringRepresentation()); } finally { entries.getReadWriteLock().writeLock().unlock(); } @@ -1220,7 +1221,7 @@ public void actionPerformed(ActionEvent actionEvent) { } } final FileListTableModel localModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(localModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(localModel::setContent); // We have a static utility method for searching for all relevant // links: JDialog diag = new JDialog(ImportInspectionDialog.this, true); @@ -1230,7 +1231,7 @@ public void actionPerformed(ActionEvent actionEvent) { entries.getReadWriteLock().writeLock().lock(); try { - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + entry.setField(FieldName.FILE, localModel.getStringRepresentation()); } finally { entries.getReadWriteLock().writeLock().unlock(); } @@ -1262,11 +1263,11 @@ public void actionPerformed(ActionEvent actionEvent) { editor.setVisible(true, true); if (editor.okPressed()) { FileListTableModel localModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(localModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(localModel::setContent); localModel.addEntry(localModel.getRowCount(), flEntry); entries.getReadWriteLock().writeLock().lock(); try { - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + entry.setField(FieldName.FILE, localModel.getStringRepresentation()); } finally { entries.getReadWriteLock().writeLock().unlock(); } @@ -1278,11 +1279,11 @@ public void actionPerformed(ActionEvent actionEvent) { public void downloadComplete(FileListEntry file) { ImportInspectionDialog.this.toFront(); // Hack FileListTableModel localModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(localModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(localModel::setContent); localModel.addEntry(localModel.getRowCount(), file); entries.getReadWriteLock().writeLock().lock(); try { - entry.setField(Globals.FILE_FIELD, localModel.getStringRepresentation()); + entry.setField(FieldName.FILE, localModel.getStringRepresentation()); } finally { entries.getReadWriteLock().writeLock().unlock(); } @@ -1305,7 +1306,7 @@ private void setupComparatorChooser() { comparators = comparatorChooser.getComparatorsForColumn(i); comparators.clear(); if (i == FILE_COL) { - comparators.add(new IconComparator(Collections.singletonList(Globals.FILE_FIELD))); + comparators.add(new IconComparator(Collections.singletonList(FieldName.FILE))); } else if (i == URL_COL) { comparators.add(new IconComparator(Collections.singletonList(URL_FIELD))); } @@ -1423,9 +1424,9 @@ public Object getColumnValue(BibEntry entry, int i) { case DUPL_COL: return entry.isGroupHit() ? duplLabel : null; case FILE_COL: - if (entry.hasField(Globals.FILE_FIELD)) { + if (entry.hasField(FieldName.FILE)) { FileListTableModel model = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(model::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(model::setContent); fileLabel.setToolTipText(model.getToolTipHTMLRepresentation()); if (model.getRowCount() > 0) { fileLabel.setIcon(model.getEntry(0).type.get().getIcon()); diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index f516c01d47c6..768e76d86f81 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -58,6 +58,7 @@ import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.search.SearchQueryHighlightListener; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.event.FieldChangedEvent; import net.sf.jabref.preferences.JabRefPreferences; @@ -240,7 +241,7 @@ public Dimension getPreferredScrollableViewportSize() { .isPresent()) { try { String address = hyperlinkEvent.getURL().toString(); - JabRefDesktop.openExternalViewer(PreviewPanel.this.databaseContext.get(), address, "url"); + JabRefDesktop.openExternalViewer(PreviewPanel.this.databaseContext.get(), address, FieldName.URL); } catch (IOException e) { LOGGER.warn("Could not open external viewer", e); } diff --git a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java index ab2a817742a9..20a7da5ffb76 100644 --- a/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/ManageKeywordsAction.java @@ -54,6 +54,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; @@ -67,8 +68,6 @@ import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; -import static net.sf.jabref.model.entry.BibEntry.KEYWORDS_FIELD; - /** * An Action for launching keyword managing dialog * @@ -195,7 +194,7 @@ public void keyPressed(KeyEvent arg0) { }); AutoCompleter autoComp = JabRefGUI.getMainFrame().getCurrentBasePanel().getAutoCompleters() - .get(KEYWORDS_FIELD); + .get(FieldName.KEYWORDS); AutoCompleteListener acl = new AutoCompleteListener(autoComp); keyword.addKeyListener(acl); keyword.addFocusListener(acl); diff --git a/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java b/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java index b3b775cac07b..67f1b962c78d 100644 --- a/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java +++ b/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java @@ -12,6 +12,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.logic.cleanup.CleanupPreset; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; @@ -60,7 +61,7 @@ private void init() { 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)); + Localization.lang("Upgrade external PDF/PS links to use the '%0' field.", FieldName.FILE)); cleanUpBibLatex = new JCheckBox(Localization.lang( "Convert to BibLatex format (for example, move the value of the 'journal' field to 'journaltitle')")); diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index 7627609ffa36..338a3cd4038a 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -49,6 +49,7 @@ import net.sf.jabref.logic.util.OS; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -95,15 +96,15 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, String fieldName = "ps"; } } - } else if ("doi".equals(fieldName)) { + } else if (FieldName.DOI.equals(fieldName)) { Optional doiUrl = DOI.build(link); if (doiUrl.isPresent()) { link = doiUrl.get().getURIAsASCIIString(); } // should be opened in browser - fieldName = "url"; + fieldName = FieldName.URL; } else if ("eprint".equals(fieldName)) { - fieldName = "url"; + fieldName = FieldName.URL; // Check to see if link field already contains a well formated URL if (!link.startsWith("http://")) { @@ -111,7 +112,7 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, String } } - if ("url".equals(fieldName)) { // html + if (FieldName.URL.equals(fieldName)) { // html try { openBrowser(link); } catch (IOException e) { @@ -228,7 +229,7 @@ public static boolean openExternalFileUnknown(JabRefFrame frame, BibEntry entry, // User wants to change the type of this link. // First get a model of all file links for this entry: FileListTableModel tModel = new FileListTableModel(); - Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + Optional oldValue = entry.getFieldOptional(FieldName.FILE); oldValue.ifPresent(tModel::setContent); FileListEntry flEntry = null; // Then find which one we are looking at: @@ -249,9 +250,9 @@ public static boolean openExternalFileUnknown(JabRefFrame frame, BibEntry entry, if (editor.okPressed()) { // Store the changes and add an undo edit: String newValue = tModel.getStringRepresentation(); - UndoableFieldChange ce = new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue.orElse(null), + UndoableFieldChange ce = new UndoableFieldChange(entry, FieldName.FILE, oldValue.orElse(null), newValue); - entry.setField(Globals.FILE_FIELD, newValue); + entry.setField(FieldName.FILE, newValue); frame.getCurrentBasePanel().getUndoManager().addEdit(ce); frame.getCurrentBasePanel().markBaseChanged(); // Finally, open the link: diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index fce31985cc19..24fb2cb53f25 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -107,6 +107,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryConverter; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.event.FieldChangedEvent; @@ -260,8 +261,8 @@ private void setupFieldPanels() { addOptionalTab(type); Set deprecatedFields = new HashSet<>(EntryConverter.FIELD_ALIASES_TEX_TO_LTX.keySet()); - deprecatedFields.add("year"); - deprecatedFields.add("month"); + deprecatedFields.add(FieldName.YEAR); + deprecatedFields.add(FieldName.MONTH); List secondaryOptionalFields = type.getSecondaryOptionalFields(); List optionalFieldsNotPrimaryOrDeprecated = new ArrayList<>(secondaryOptionalFields); optionalFieldsNotPrimaryOrDeprecated.removeAll(deprecatedFields); @@ -306,7 +307,7 @@ private void setupFieldPanels() { // other fields List displayedFields = Stream.concat(requiredFields.stream(), displayedOptionalFields.stream()).map(String::toLowerCase).collect(Collectors.toList()); List otherFields = entry.getFieldNames().stream().map(String::toLowerCase).filter(f -> !displayedFields.contains(f)).collect(Collectors.toList()); - otherFields.remove("bibtexkey"); + otherFields.remove(BibEntry.KEY_FIELD); otherFields.removeAll(Globals.prefs.getCustomTabFieldNames()); if (!otherFields.isEmpty()) { diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java index 186b9054976d..f12a5804ea03 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/FieldExtraComponents.java @@ -53,6 +53,7 @@ import net.sf.jabref.logic.util.date.EasyDateFormat; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; @@ -189,7 +190,7 @@ public static Optional getDoiExtraComponent(BasePanel panel, EntryEd doiButton.addActionListener(actionEvent -> { Optional doi = DOI.fromBibEntry(entryEditor.getEntry()); if (doi.isPresent()) { - entryEditor.getEntry().setField("doi", doi.get().getDOI()); + entryEditor.getEntry().setField(FieldName.DOI, doi.get().getDOI()); } else { panel.frame().setStatus(Localization.lang("No DOI found")); } diff --git a/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java b/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java index 142a374e5740..89c854092cf2 100644 --- a/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java +++ b/src/main/java/net/sf/jabref/gui/fieldeditors/FieldNameLabel.java @@ -25,6 +25,7 @@ import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; public class FieldNameLabel extends JLabel { @@ -48,15 +49,15 @@ public void paintComponent(Graphics g) { private static String getFieldNameLabelText(String fieldName) { // selected terms should be uppercase - if("isbn".equalsIgnoreCase(fieldName)) { + if(FieldName.ISBN.equalsIgnoreCase(fieldName)) { return " ISBN "; - } else if ("url".equalsIgnoreCase(fieldName)){ + } else if (FieldName.URL.equalsIgnoreCase(fieldName)){ return " URL "; } else if ("uri".equalsIgnoreCase(fieldName)) { return " URI "; - } else if ("issn".equalsIgnoreCase(fieldName)) { + } else if (FieldName.ISSN.equalsIgnoreCase(fieldName)) { return " ISSN "; - } else if("doi".equalsIgnoreCase(fieldName)) { + } else if(FieldName.DOI.equalsIgnoreCase(fieldName)) { return " DOI "; } else if("isrn".equalsIgnoreCase(fieldName)) { return " ISRN "; diff --git a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java index 8f658a05a17b..d2c319917ad6 100644 --- a/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/AutoGroupDialog.java @@ -49,6 +49,7 @@ import net.sf.jabref.logic.groups.GroupsUtil; import net.sf.jabref.logic.groups.KeywordGroup; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.FieldName; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.FormBuilder; @@ -109,14 +110,14 @@ public void actionPerformed(ActionEvent e) { } } else if (authors.isSelected()) { List fields = new ArrayList<>(2); - fields.add("author"); + fields.add(FieldName.AUTHOR); hs = GroupsUtil.findAuthorLastNames(panel.getDatabase(), fields); - fieldText = "author"; + fieldText = FieldName.AUTHOR; } else { // editors.isSelected() as it is a radio button group. List fields = new ArrayList<>(2); - fields.add("editor"); + fields.add(FieldName.EDITOR); hs = GroupsUtil.findAuthorLastNames(panel.getDatabase(), fields); - fieldText = "editor"; + fieldText = FieldName.EDITOR; } for (String keyword : hs) { diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java index 18932a7d4b35..11af83d908f1 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupDialog.java @@ -57,6 +57,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; @@ -89,7 +90,7 @@ class GroupDialog extends JDialog { Localization.lang("Include subgroups: When selected, view entries contained in this group or its subgroups")); // for KeywordGroup private final JTextField keywordGroupSearchField = new JTextField(GroupDialog.TEXTFIELD_LENGTH); - private final TextField keywordGroupSearchTerm = new TextField("keywords", "", false); + private final TextField keywordGroupSearchTerm = new TextField(FieldName.KEYWORDS, "", false); private final JCheckBox keywordGroupCaseSensitive = new JCheckBox(Localization.lang("Case sensitive")); private final JCheckBox keywordGroupRegExp = new JCheckBox(Localization.lang("regular expression")); // for SearchGroup diff --git a/src/main/java/net/sf/jabref/gui/groups/WarnAssignmentSideEffects.java b/src/main/java/net/sf/jabref/gui/groups/WarnAssignmentSideEffects.java index 524b83f3fdf1..81406583f3f2 100644 --- a/src/main/java/net/sf/jabref/gui/groups/WarnAssignmentSideEffects.java +++ b/src/main/java/net/sf/jabref/gui/groups/WarnAssignmentSideEffects.java @@ -10,6 +10,7 @@ import net.sf.jabref.logic.groups.AbstractGroup; import net.sf.jabref.logic.groups.KeywordGroup; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.InternalBibtexFields; public class WarnAssignmentSideEffects { @@ -30,7 +31,7 @@ public static boolean warnAssignmentSideEffects(List groups, Comp if (group instanceof KeywordGroup) { KeywordGroup keywordGroup = (KeywordGroup) group; String field = keywordGroup.getSearchField().toLowerCase(); - if ("keywords".equals(field) || "groups".equals(field)) { + if (FieldName.KEYWORDS.equals(field) || "groups".equals(field)) { continue; // this is not undesired } int len = InternalBibtexFields.numberOfPublicFields(); diff --git a/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java b/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java index ac94c7899d43..26a42cfab765 100644 --- a/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java +++ b/src/main/java/net/sf/jabref/gui/journals/AbbreviateAction.java @@ -24,6 +24,7 @@ import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Converts journal full names to either iso or medline abbreviations for all selected entries. @@ -60,10 +61,10 @@ public void run() { NamedCompound ce = new NamedCompound(Localization.lang("Abbreviate journal names")); int count = 0; for (BibEntry entry : entries) { - if (undoableAbbreviator.abbreviate(panel.getDatabase(), entry, "journal", ce)) { + if (undoableAbbreviator.abbreviate(panel.getDatabase(), entry, FieldName.JOURNAL, ce)) { count++; } - if (undoableAbbreviator.abbreviate(panel.getDatabase(), entry, "journaltitle", ce)) { + if (undoableAbbreviator.abbreviate(panel.getDatabase(), entry, FieldName.JOURNALTITLE, ce)) { count++; } } diff --git a/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java b/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java index 28b5a3a505b6..c4c603a365ad 100644 --- a/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java +++ b/src/main/java/net/sf/jabref/gui/journals/UnabbreviateAction.java @@ -24,6 +24,7 @@ import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Converts journal abbreviations back to full name for all selected entries. @@ -57,10 +58,10 @@ public void run() { NamedCompound ce = new NamedCompound(Localization.lang("Unabbreviate journal names")); int count = 0; for (BibEntry entry : entries) { - if (undoableAbbreviator.unabbreviate(panel.getDatabase(), entry, "journal", ce)) { + if (undoableAbbreviator.unabbreviate(panel.getDatabase(), entry, FieldName.JOURNAL, ce)) { count++; } - if (undoableAbbreviator.unabbreviate(panel.getDatabase(), entry, "journaltitle", ce)) { + if (undoableAbbreviator.unabbreviate(panel.getDatabase(), entry, FieldName.JOURNALTITLE, ce)) { count++; } } diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java index 7820447c2531..98dba92fda21 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTable.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTable.java @@ -58,6 +58,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexSingleField; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; @@ -499,7 +500,7 @@ public int findEntry(BibEntry entry) { */ public boolean isFileColumn(int modelIndex) { return (tableFormat.getTableColumn(modelIndex) != null) && tableFormat.getTableColumn(modelIndex) - .getBibtexFields().contains(Globals.FILE_FIELD); + .getBibtexFields().contains(FieldName.FILE); } private boolean matches(int row, Matcher m) { diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java index a1067fd3d521..92105340a819 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java @@ -26,6 +26,7 @@ import net.sf.jabref.gui.IconTheme; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldsUtils; @@ -38,8 +39,8 @@ public class MainTableFormat implements TableFormat { // Values to gather iconImages for those columns // These values are also used to put a heading into the table; see getColumnName(int) - private static final List URL_FIRST = Arrays.asList("url", "doi"); - private static final List DOI_FIRST = Arrays.asList("doi", "url"); + private static final List URL_FIRST = Arrays.asList(FieldName.URL, FieldName.DOI); + private static final List DOI_FIRST = Arrays.asList(FieldName.DOI, FieldName.URL); private static final List ARXIV = Collections.singletonList("eprint"); private final BibDatabase database; diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index a7cc08f86c70..8068fa6933ff 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -49,6 +49,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.SpecialFieldValue; import net.sf.jabref.specialfields.SpecialFieldsUtils; @@ -296,7 +297,7 @@ public void mouseClicked(MouseEvent e) { // See if this is a simple file link field, or if it is a file-list // field that can specify a list of links: - if (fieldName.equals(Globals.FILE_FIELD)) { + if (fieldName.equals(FieldName.FILE)) { // We use a FileListTableModel to parse the field content: FileListTableModel fileList = new FileListTableModel(); @@ -336,8 +337,8 @@ public void mouseClicked(MouseEvent e) { } } }); - } else if (modelColumn.getBibtexFields().contains("crossref")) { // Clicking on crossref column - tableRows.get(row).getFieldOptional("crossref") + } else if (modelColumn.getBibtexFields().contains(FieldName.CROSSREF)) { // Clicking on crossref column + tableRows.get(row).getFieldOptional(FieldName.CROSSREF) .ifPresent(crossref -> panel.getDatabase().getEntryByKey(crossref).ifPresent(entry -> panel.highlightEntry(entry))); } } @@ -400,7 +401,7 @@ private void showIconRightClickMenu(MouseEvent e, int row, MainTableColumn colum // field that can specify a list of links: if(!column.getBibtexFields().isEmpty()) { for(String field : column.getBibtexFields()) { - if (Globals.FILE_FIELD.equals(field)) { + if (FieldName.FILE.equals(field)) { // We use a FileListTableModel to parse the field content: FileListTableModel fileList = new FileListTableModel(); entry.getFieldOptional(field).ifPresent(fileList::setContent); diff --git a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java index 7ce3a75e92dc..74a0ed39aaac 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java +++ b/src/main/java/net/sf/jabref/gui/maintable/SpecialMainTableColumns.java @@ -6,12 +6,12 @@ import javax.swing.JLabel; -import net.sf.jabref.Globals; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.GUIGlobals; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.specialfields.Printed; import net.sf.jabref.specialfields.Priority; @@ -99,14 +99,14 @@ public Object getColumnValue(BibEntry entry) { new JLabel(Quality.getInstance().getRepresentingIcon())); - public static final MainTableColumn FILE_COLUMN = new MainTableColumn(Globals.FILE_FIELD, - Collections.singletonList(Globals.FILE_FIELD), new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon())) { + public static final MainTableColumn FILE_COLUMN = new MainTableColumn(FieldName.FILE, + Collections.singletonList(FieldName.FILE), new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon())) { @Override public Object getColumnValue(BibEntry entry) { // We use a FileListTableModel to parse the field content: FileListTableModel fileList = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileList::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(fileList::setContent); if (fileList.getRowCount() > 1) { return new JLabel(IconTheme.JabRefIcon.FILE_MULTIPLE.getSmallIcon()); } else if (fileList.getRowCount() == 1) { @@ -167,7 +167,7 @@ public static MainTableColumn createFileIconColumn(String externalFileTypeName) - return new MainTableColumn(externalFileTypeName, Collections.singletonList(Globals.FILE_FIELD), new JLabel()) { + return new MainTableColumn(externalFileTypeName, Collections.singletonList(FieldName.FILE), new JLabel()) { @Override public boolean isFileFilter() { @@ -185,7 +185,7 @@ public Object getColumnValue(BibEntry entry) { boolean iconFound = false; JLabel iconLabel = null; FileListTableModel fileList = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileList::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(fileList::setContent); for (int i = 0; i < fileList.getRowCount(); i++) { if ((fileList.getEntry(i).type.isPresent()) && externalFileTypeName.equalsIgnoreCase(fileList.getEntry(i).type.get().getName())) { diff --git a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java index 28c6dab4b9e6..8103793f7b32 100644 --- a/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/RightClickMenu.java @@ -39,6 +39,7 @@ import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.specialfields.Printed; @@ -156,7 +157,7 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) { add(new GeneralAction(Actions.OPEN_FOLDER, Localization.lang("Open folder")) { { - if (!isFieldSetForSelectedEntry(Globals.FILE_FIELD)) { + if (!isFieldSetForSelectedEntry(FieldName.FILE)) { this.setEnabled(false); } } @@ -164,7 +165,7 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) { add(new GeneralAction(Actions.OPEN_EXTERNAL_FILE, Localization.lang("Open file"), getFileIconForSelectedEntry()) { { - if (!isFieldSetForSelectedEntry(Globals.FILE_FIELD)) { + if (!isFieldSetForSelectedEntry(FieldName.FILE)) { this.setEnabled(false); } } @@ -172,7 +173,7 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) { add(new GeneralAction(Actions.OPEN_URL, Localization.lang("Open URL or DOI"), IconTheme.JabRefIcon.WWW.getSmallIcon()) { { - if(!(isFieldSetForSelectedEntry("url") || isFieldSetForSelectedEntry("doi"))) { + if(!(isFieldSetForSelectedEntry(FieldName.URL) || isFieldSetForSelectedEntry(FieldName.DOI))) { this.setEnabled(false); } } @@ -184,7 +185,7 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) { add(new GeneralAction(Actions.MERGE_DOI, Localization.lang("Get BibTeX data from DOI")) { { - if (!(isFieldSetForSelectedEntry("doi"))) { + if (!(isFieldSetForSelectedEntry(FieldName.DOI))) { this.setEnabled(false); } } @@ -279,8 +280,8 @@ private boolean isFieldSetForSelectedEntry(String fieldname) { private Icon getFileIconForSelectedEntry() { if (panel.getMainTable().getSelectedRowCount() == 1) { BibEntry entry = panel.getMainTable().getSelected().get(0); - if(entry.hasField(Globals.FILE_FIELD)) { - JLabel label = FileListTableModel.getFirstLabel(entry.getFieldOptional(Globals.FILE_FIELD).get()); + if(entry.hasField(FieldName.FILE)) { + JLabel label = FileListTableModel.getFirstLabel(entry.getFieldOptional(FieldName.FILE).get()); if (label != null) { return label.getIcon(); } diff --git a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java index 97cf3d07f613..0c3e2b77b0ae 100644 --- a/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java +++ b/src/main/java/net/sf/jabref/gui/mergeentries/MergeEntryDOIDialog.java @@ -32,6 +32,7 @@ import net.sf.jabref.importer.fetcher.DOItoBibTeXFetcher; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.preferences.JabRefPreferences; @@ -73,7 +74,7 @@ public MergeEntryDOIDialog(BasePanel panel) { this.originalEntry = panel.getSelectedEntries().get(0); panel.output(Localization.lang("Fetching info based on DOI")); - Optional doi = this.originalEntry.getFieldOptional("doi"); + Optional doi = this.originalEntry.getFieldOptional(FieldName.DOI); if (doi.isPresent()) { this.doiEntry = doiFetcher.getEntryFromDOI(doi.get()).orElse(null); diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java index 019a4a54cbad..3ec5e3d9cc66 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OOBibBase.java @@ -56,6 +56,7 @@ import net.sf.jabref.logic.openoffice.UndefinedParagraphFormatException; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import com.sun.star.awt.Point; import com.sun.star.beans.IllegalTypeException; @@ -134,9 +135,9 @@ class OOBibBase { private final boolean atEnd; private final Comparator entryComparator; private final Comparator yearAuthorTitleComparator; - private final FieldComparator authComp = new FieldComparator("author"); - private final FieldComparator yearComp = new FieldComparator("year"); - private final FieldComparator titleComp = new FieldComparator("title"); + private final FieldComparator authComp = new FieldComparator(FieldName.AUTHOR); + private final FieldComparator yearComp = new FieldComparator(FieldName.YEAR); + private final FieldComparator titleComp = new FieldComparator(FieldName.TITLE); private final List> authorYearTitleList = new ArrayList<>(3); private final List> yearAuthorTitleList = new ArrayList<>(3); @@ -1214,7 +1215,7 @@ public void combineCiteMarkers(List databases, OOBibStyle style) th } } } - Collections.sort(entries, new FieldComparator("year")); + Collections.sort(entries, new FieldComparator(FieldName.YEAR)); String keyString = String.join(",", entries.stream().map(BibEntry::getCiteKey).collect(Collectors.toList())); // Insert bookmark: diff --git a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java index c59727628b2b..89bc47ee2e21 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java @@ -64,6 +64,7 @@ import net.sf.jabref.logic.openoffice.OpenOfficePreferences; import net.sf.jabref.logic.openoffice.StyleLoader; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.preferences.JabRefPreferences; @@ -372,13 +373,13 @@ private Optional getSelectedStyle() { } private void setupPrevEntry() { - prevEntry.setField("author", "Smith, Bill and Jones, Bob and Williams, Jeff"); - prevEntry.setField("editor", "Taylor, Phil"); - prevEntry.setField("title", "Title of the test entry for reference styles"); - prevEntry.setField("volume", "34"); - prevEntry.setField("year", "2008"); - prevEntry.setField("journal", "BibTeX journal"); - prevEntry.setField("publisher", "JabRef publishing"); + prevEntry.setField(FieldName.AUTHOR, "Smith, Bill and Jones, Bob and Williams, Jeff"); + prevEntry.setField(FieldName.EDITOR, "Taylor, Phil"); + prevEntry.setField(FieldName.TITLE, "Title of the test entry for reference styles"); + prevEntry.setField(FieldName.VOLUME, "34"); + prevEntry.setField(FieldName.YEAR, "2008"); + prevEntry.setField(FieldName.JOURNAL, "BibTeX journal"); + prevEntry.setField(FieldName.PUBLISHER, "JabRef publishing"); prevEntry.setField("address", "Trondheim"); prevEntry.setField("www", "https://github.com/JabRef"); } diff --git a/src/main/java/net/sf/jabref/gui/openoffice/UndefinedBibtexEntry.java b/src/main/java/net/sf/jabref/gui/openoffice/UndefinedBibtexEntry.java index 4b7e43d8e523..fae53bfa2b0e 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/UndefinedBibtexEntry.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/UndefinedBibtexEntry.java @@ -17,6 +17,7 @@ import net.sf.jabref.logic.openoffice.OOBibStyle; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; /** @@ -31,7 +32,7 @@ class UndefinedBibtexEntry extends BibEntry { public UndefinedBibtexEntry(String key) { super(IdGenerator.next()); this.key = key; - setField("author", OOBibStyle.UNDEFINED_CITATION_MARKER); + setField(FieldName.AUTHOR, OOBibStyle.UNDEFINED_CITATION_MARKER); } public String getKey() { diff --git a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java index 4107bb59e613..86771d7628d9 100644 --- a/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java +++ b/src/main/java/net/sf/jabref/gui/plaintextimport/TextInputDialog.java @@ -129,6 +129,7 @@ import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.preferences.JabRefPreferences; @@ -475,7 +476,7 @@ private void insertTextForTag(boolean overrideField) { // insert a new name with an additional "and" if (InternalBibtexFields.getFieldExtras(fieldName).contains(FieldProperties.PERSON_NAMES)) { entry.setField(fieldName, old.get() + " and " + txt); - } else if ("keywords".equals(fieldName)) { + } else if (FieldName.KEYWORDS.equals(fieldName)) { // Add keyword entry.addKeyword(txt, Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); } else { diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index 444ad9a57ae6..fbd93aeac6d6 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -37,6 +37,7 @@ import net.sf.jabref.gui.help.HelpAction; import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; @@ -199,7 +200,7 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { @Override public void setValues() { - fileDir.setText(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); + fileDir.setText(prefs.get(FieldName.FILE + Globals.DIR_SUFFIX)); bibLocAsPrimaryDir.setSelected(prefs.getBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR)); runAutoFileSearch.setSelected(prefs.getBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH)); allowFileAutoOpenBrowse.setSelected(prefs.getBoolean(JabRefPreferences.ALLOW_FILE_AUTO_OPEN_BROWSE)); @@ -240,7 +241,7 @@ public void setValues() { @Override public void storeSettings() { - prefs.put(Globals.FILE_FIELD + Globals.DIR_SUFFIX, fileDir.getText()); + prefs.put(FieldName.FILE + Globals.DIR_SUFFIX, fileDir.getText()); prefs.putBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR, bibLocAsPrimaryDir.isSelected()); prefs.putBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH, runAutoFileSearch.isSelected()); prefs.putBoolean(JabRefPreferences.ALLOW_FILE_AUTO_OPEN_BROWSE, allowFileAutoOpenBrowse.isSelected()); diff --git a/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java index 8c0a7cb4a625..0cb3e3eeb834 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/PreviewPrefsTab.java @@ -32,6 +32,7 @@ import net.sf.jabref.gui.PreviewPanel; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.preferences.JabRefPreferences; @@ -190,20 +191,20 @@ private static BibEntry getTestEntry() { } PreviewPrefsTab.entry = new BibEntry(IdGenerator.next(), "article"); PreviewPrefsTab.entry.setCiteKey("conceicao1997"); - PreviewPrefsTab.entry.setField("author", + PreviewPrefsTab.entry.setField(FieldName.AUTHOR, "Luis E. C. Conceic{\\~a}o and Terje van der Meeren and Johan A. J. Verreth and M S. Evjen and D. F. Houlihan and H. J. Fyhn"); - PreviewPrefsTab.entry.setField("title", + PreviewPrefsTab.entry.setField(FieldName.TITLE, "Amino acid metabolism and protein turnover in larval turbot (Scophthalmus maximus) fed natural zooplankton or Artemia"); - PreviewPrefsTab.entry.setField("year", "1997"); - PreviewPrefsTab.entry.setField("journal", "Marine Biology"); - PreviewPrefsTab.entry.setField("month", "January"); - PreviewPrefsTab.entry.setField("number", "2"); - PreviewPrefsTab.entry.setField("volume", "123"); + PreviewPrefsTab.entry.setField(FieldName.YEAR, "1997"); + PreviewPrefsTab.entry.setField(FieldName.JOURNAL, "Marine Biology"); + PreviewPrefsTab.entry.setField(FieldName.MONTH, "January"); + PreviewPrefsTab.entry.setField(FieldName.NUMBER, "2"); + PreviewPrefsTab.entry.setField(FieldName.VOLUME, "123"); PreviewPrefsTab.entry.setField("pdf", "conceicao1997.pdf"); - PreviewPrefsTab.entry.setField("pages", "255--265"); - PreviewPrefsTab.entry.setField("keywords", "energetics, artemia, metabolism, amino acid, turbot"); - PreviewPrefsTab.entry.setField("url", "http://ejournals.ebsco.com/direct.asp?ArticleID=TYY4NT82XA9H7R8PFPPV"); - PreviewPrefsTab.entry.setField("abstract", + PreviewPrefsTab.entry.setField(FieldName.PAGES, "255--265"); + PreviewPrefsTab.entry.setField(FieldName.KEYWORDS, "energetics, artemia, metabolism, amino acid, turbot"); + PreviewPrefsTab.entry.setField(FieldName.URL, "http://ejournals.ebsco.com/direct.asp?ArticleID=TYY4NT82XA9H7R8PFPPV"); + PreviewPrefsTab.entry.setField(FieldName.ABSTRACT, "Abstract The present paper studied the influence of different food regimes " + "on the free amino acid (FAA) pool, the rate of protein turnover, the flux of amino acids, and " + "their relation to growth of larval turbot (Scophthalmus maximus L.) from first feeding until " diff --git a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java index ea5a5e5c2267..a93ff9259256 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchResultsDialog.java @@ -66,6 +66,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.preferences.JabRefPreferences; @@ -96,7 +97,7 @@ public class SearchResultsDialog { private JDialog diag; private static final String[] FIELDS = new String[] { - "author", "title", "year", "journal" + FieldName.AUTHOR, FieldName.TITLE, FieldName.YEAR, FieldName.JOURNAL }; private static final int FILE_COL = 0; private static final int URL_COL = 1; @@ -130,7 +131,7 @@ private void init(String title) { .get(JabRefPreferences.PREVIEW_1); preview = new PreviewPanel(null, null, layoutFile); - sortedEntries = new SortedList<>(entries, new EntryComparator(false, true, "author")); + sortedEntries = new SortedList<>(entries, new EntryComparator(false, true, FieldName.AUTHOR)); model = (DefaultEventTableModel) GlazedListsSwing.eventTableModelWithThreadProxyList(sortedEntries, new EntryTableFormat()); entryTable = new JTable(model); @@ -238,9 +239,9 @@ private void setupComparatorChooser(TableComparatorChooser comparatorC comparators = comparatorChooser.getComparatorsForColumn(i); comparators.clear(); if (i == FILE_COL) { - comparators.add(new IconComparator(Collections.singletonList(Globals.FILE_FIELD))); + comparators.add(new IconComparator(Collections.singletonList(FieldName.FILE))); } else if (i == URL_COL) { - comparators.add(new IconComparator(Collections.singletonList("url"))); + comparators.add(new IconComparator(Collections.singletonList(FieldName.URL))); } } @@ -346,9 +347,9 @@ public void mouseClicked(MouseEvent e) { BasePanel p = entryHome.get(entry); switch (col) { case FILE_COL: - if (entry.hasField(Globals.FILE_FIELD)) { + if (entry.hasField(FieldName.FILE)) { FileListTableModel tableModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tableModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(tableModel::setContent); if (tableModel.getRowCount() == 0) { return; } @@ -358,8 +359,8 @@ public void mouseClicked(MouseEvent e) { } break; case URL_COL: - entry.getFieldOptional("url").ifPresent(link -> { try { - JabRefDesktop.openExternalViewer(p.getBibDatabaseContext(), link, "url"); + entry.getFieldOptional(FieldName.URL).ifPresent(link -> { try { + JabRefDesktop.openExternalViewer(p.getBibDatabaseContext(), link, FieldName.URL); } catch (IOException ex) { LOGGER.warn("Could not open viewer", ex); } @@ -388,7 +389,7 @@ public void processPopupTrigger(MouseEvent e) { if (col == FILE_COL) { // We use a FileListTableModel to parse the field content: FileListTableModel fileList = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileList::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(fileList::setContent); // If there are one or more links, open the first one: for (int i = 0; i < fileList.getRowCount(); i++) { FileListEntry flEntry = fileList.getEntry(i); @@ -456,9 +457,9 @@ public Object getColumnValue(BibEntry entry, int column) { if (column < PAD) { switch (column) { case FILE_COL: - if (entry.hasField(Globals.FILE_FIELD)) { + if (entry.hasField(FieldName.FILE)) { FileListTableModel tmpModel = new FileListTableModel(); - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(tmpModel::setContent); + entry.getFieldOptional(FieldName.FILE).ifPresent(tmpModel::setContent); fileLabel.setToolTipText(tmpModel.getToolTipHTMLRepresentation()); if (tmpModel.getRowCount() > 0) { if (tmpModel.getEntry(0).type.isPresent()) { @@ -472,8 +473,8 @@ public Object getColumnValue(BibEntry entry, int column) { return null; } case URL_COL: - if (entry.hasField("url")) { - urlLabel.setToolTipText(entry.getFieldOptional("url").get()); + if (entry.hasField(FieldName.URL)) { + urlLabel.setToolTipText(entry.getFieldOptional(FieldName.URL).get()); return urlLabel; } else { return null; diff --git a/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java b/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java index 88ac36c398a3..7f57212264c0 100644 --- a/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java +++ b/src/main/java/net/sf/jabref/importer/DatabaseFileLookup.java @@ -23,11 +23,11 @@ import java.util.Optional; import java.util.Set; -import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; 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.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; @@ -80,7 +80,7 @@ public boolean lookupDatabase(File file) { private List parseFileField(BibEntry entry) { Objects.requireNonNull(entry); - List entries = FileField.parse(entry.getFieldOptional(Globals.FILE_FIELD).orElse(null)); + List entries = FileField.parse(entry.getFieldOptional(FieldName.FILE).orElse(null)); List fileLinks = new ArrayList<>(); for (ParsedFileField field : entries) { diff --git a/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java b/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java index f36d7a80cef0..3a845164a007 100644 --- a/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java +++ b/src/main/java/net/sf/jabref/importer/EntryFromFileCreator.java @@ -21,7 +21,6 @@ import java.util.Optional; import java.util.StringTokenizer; -import net.sf.jabref.Globals; import net.sf.jabref.JabRefGUI; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.external.ExternalFileTypes; @@ -29,6 +28,7 @@ import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * The interface EntryFromFileCreator does twice:
    @@ -108,11 +108,11 @@ public Optional createEntry(File f, boolean addPathTokensAsKeywords) { } if (addPathTokensAsKeywords) { - appendToField(newEntry.get(), "keywords", extractPathesToKeyWordsfield(f.getAbsolutePath())); + appendToField(newEntry.get(), FieldName.KEYWORDS, extractPathesToKeyWordsfield(f.getAbsolutePath())); } - if (!newEntry.get().hasField("title")) { - newEntry.get().setField("title", f.getName()); + if (!newEntry.get().hasField(FieldName.TITLE)) { + newEntry.get().setField(FieldName.TITLE, f.getName()); } addFileInfo(newEntry.get(), f); @@ -162,7 +162,7 @@ private void addFileInfo(BibEntry entry, File file) { FileListTableModel model = new FileListTableModel(); model.addEntry(0, fileListEntry); - entry.setField(Globals.FILE_FIELD, model.getStringRepresentation()); + entry.setField(FieldName.FILE, model.getStringRepresentation()); } protected void appendToField(BibEntry entry, String field, String value) { diff --git a/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java b/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java index 49b2efd4add1..bd2c4cec29db 100644 --- a/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java +++ b/src/main/java/net/sf/jabref/importer/EntryFromPDFCreator.java @@ -14,6 +14,7 @@ import net.sf.jabref.gui.IconTheme; import net.sf.jabref.logic.xmp.XMPUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.pdfimport.PdfImporter; import net.sf.jabref.pdfimport.PdfImporter.ImportPdfFilesResult; @@ -69,8 +70,8 @@ protected Optional createBibtexEntry(File pdfFile) { /*addEntryDataFromPDDocumentInformation(pdfFile, entry); addEntryDataFromXMP(pdfFile, entry); - if (entry.getField("title") == null) { - entry.setField("title", pdfFile.getName()); + if (entry.getField(FieldName.TITLE) == null) { + entry.setField(FieldName.TITLE, pdfFile.getName()); } return entry;*/ @@ -96,7 +97,7 @@ private void addEntryDataFromPDDocumentInformation(File pdfFile, BibEntry entry) // default time stamp follows ISO-8601. Reason: https://xkcd.com/1179/ String date = new SimpleDateFormat("yyyy-MM-dd") .format(creationDate.getTime()); - appendToField(entry, "timestamp", date); + appendToField(entry, InternalBibtexFields.TIMESTAMP, date); } if (pdfDocInfo.getCustomMetadataValue("bibtex/bibtexkey") != null) { diff --git a/src/main/java/net/sf/jabref/importer/OAI2Handler.java b/src/main/java/net/sf/jabref/importer/OAI2Handler.java index 101386ecb02a..c46dfbf65313 100644 --- a/src/main/java/net/sf/jabref/importer/OAI2Handler.java +++ b/src/main/java/net/sf/jabref/importer/OAI2Handler.java @@ -18,6 +18,7 @@ import java.util.Optional; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.xml.sax.Attributes; import org.xml.sax.SAXException; @@ -79,34 +80,34 @@ public void endElement(String uri, String localName, String qualifiedName) throw forenames = content; } else if ("journal-ref".equals(qualifiedName)) { String journal = content.replaceFirst("[0-9].*", ""); - entry.setField("journal", journal); + entry.setField(FieldName.JOURNAL, journal); String volume = content.replaceFirst(journal, ""); volume = volume.replaceFirst(" .*", ""); - entry.setField("volume", volume); + entry.setField(FieldName.VOLUME, volume); String year = content.replaceFirst(".*?\\(", ""); year = year.replaceFirst("\\).*", ""); - entry.setField("year", year); + entry.setField(FieldName.YEAR, year); String pages = content.replaceFirst(journal, ""); pages = pages.replaceFirst(volume, ""); pages = pages.replaceFirst("\\(" + year + "\\)", ""); pages = pages.replace(" ", ""); - entry.setField("pages", pages); + entry.setField(FieldName.PAGES, pages); } else if ("datestamp".equals(qualifiedName)) { - Optional year = entry.getFieldOptional("year"); + Optional year = entry.getFieldOptional(FieldName.YEAR); if (!year.isPresent() || year.get().isEmpty()) { - entry.setField("year", content.replaceFirst("-.*", "")); + entry.setField(FieldName.YEAR, content.replaceFirst("-.*", "")); } - } else if ("title".equals(qualifiedName)) { - entry.setField("title", content); + } else if (FieldName.TITLE.equals(qualifiedName)) { + entry.setField(FieldName.TITLE, content); } else if ("abstract".equals(qualifiedName)) { - entry.setField("abstract", content); + entry.setField(FieldName.ABSTRACT, content); } else if ("comments".equals(qualifiedName)) { entry.setField("comments", content); } else if ("report-no".equals(qualifiedName)) { entry.setField("reportno", content); - } else if("doi".equals(qualifiedName)) { - entry.setField("doi", content); - } else if ("author".equals(qualifiedName)) { + } else if(FieldName.DOI.equals(qualifiedName)) { + entry.setField(FieldName.DOI, content); + } else if (FieldName.AUTHOR.equals(qualifiedName)) { String author = forenames + " " + keyname; if (authors.length() > 0) { authors.append(" and "); @@ -117,7 +118,7 @@ public void endElement(String uri, String localName, String qualifiedName) throw @Override public void endDocument() throws SAXException { - entry.setField("author", authors.toString()); + entry.setField(FieldName.AUTHOR, authors.toString()); } } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java index 4d019069515e..44fcaf7b6726 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java @@ -53,6 +53,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -196,7 +197,7 @@ public void getEntries(Map selection, ImportInspector inspector if (selentry.getValue()) { downloadEntryBibTeX(selentry.getKey(), fetchAbstract).ifPresent(entry -> { // Convert from HTML and optionally add curly brackets around key words to keep the case - entry.getFieldOptional("title").ifPresent(title -> { + entry.getFieldOptional(FieldName.TITLE).ifPresent(title -> { title = title.replace("\\&", "&").replace("\\#", "#"); title = convertHTMLChars(title); @@ -209,11 +210,11 @@ public void getEntries(Map selection, ImportInspector inspector if (Globals.prefs.getBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH)) { title = protectTermsFormatter.format(title); } - entry.setField("title", title); + entry.setField(FieldName.TITLE, title); }); - entry.getFieldOptional("abstract") - .ifPresent(abstr -> entry.setField("abstract", convertHTMLChars(abstr))); + entry.getFieldOptional(FieldName.ABSTRACT) + .ifPresent(abstr -> entry.setField(FieldName.ABSTRACT, convertHTMLChars(abstr))); inspector.addEntry(entry); }); } @@ -355,7 +356,7 @@ private static Optional downloadEntryBibTeX(String id, boolean downloa Matcher absM = ACMPortalFetcher.ABSTRACT_PATTERN.matcher(page); if (absM.find()) { - entry.setField("abstract", absM.group(1).trim()); + entry.setField(FieldName.ABSTRACT, absM.group(1).trim()); } Thread.sleep(ACMPortalFetcher.WAIT_TIME);//wait between requests or you will be blocked by ACM } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java index 54695aaf0143..b8818deab06f 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java @@ -47,6 +47,7 @@ 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.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -159,7 +160,7 @@ private void importADSAbstract(String key, BibEntry entry, OutputPrinter status) while (reader.hasNext()) { reader.next(); if (reader.isStartElement() && - "abstract".equals(reader.getLocalName())) { + FieldName.ABSTRACT.equals(reader.getLocalName())) { isAbstract = true; } if (isAbstract && reader.isCharacters()) { @@ -171,7 +172,7 @@ private void importADSAbstract(String key, BibEntry entry, OutputPrinter status) } String abstractText = abstractSB.toString(); abstractText = abstractText.replace("\n", " "); - entry.setField("abstract", abstractText); + entry.setField(FieldName.ABSTRACT, abstractText); } catch (XMLStreamException e) { status.showMessage(Localization.lang("An Error occurred while parsing abstract"), getTitle(), JOptionPane.ERROR_MESSAGE); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java index 29d9e8aa8f43..b1f8e14876e7 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java @@ -32,6 +32,7 @@ import net.sf.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import org.apache.commons.logging.Log; @@ -146,25 +147,25 @@ private static BibEntry getSingleCitation(String urlString) throws IOException { Matcher m = CiteSeerXFetcher.TITLE_PATTERN.matcher(cont); if (m.find()) { BibEntry entry = new BibEntry(IdGenerator.next()); - entry.setField("title", m.group(1)); + entry.setField(FieldName.TITLE, m.group(1)); // Find authors: m = CiteSeerXFetcher.AUTHOR_PATTERN.matcher(cont); if (m.find()) { String authors = m.group(1); - entry.setField("author", new NormalizeNamesFormatter().format(authors)); + entry.setField(FieldName.AUTHOR, new NormalizeNamesFormatter().format(authors)); } // Find year: m = CiteSeerXFetcher.YEAR_PATTERN.matcher(cont); if (m.find()) { - entry.setField("year", m.group(1)); + entry.setField(FieldName.YEAR, m.group(1)); } // Find abstract: m = CiteSeerXFetcher.ABSTRACT_PATTERN.matcher(cont); if (m.find()) { - entry.setField("abstract", m.group(1)); + entry.setField(FieldName.ABSTRACT, m.group(1)); } return entry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java index da6ef06683c9..f0896597ad3b 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossRef.java @@ -8,6 +8,7 @@ import net.sf.jabref.logic.layout.format.LatexToUnicodeFormatter; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.JsonNode; @@ -37,7 +38,7 @@ public static Optional findDOI(BibEntry entry) { Optional doi = Optional.empty(); // title is minimum requirement - Optional title = entry.getFieldOptional("title"); + Optional title = entry.getFieldOptional(FieldName.TITLE); if (!title.isPresent() || title.get().isEmpty()) { return doi; @@ -67,14 +68,14 @@ public static Optional findDOI(BibEntry entry) { private static String enhanceQuery(String query, BibEntry entry) { StringBuilder enhancedQuery = new StringBuilder(query); // author - entry.getFieldOptional("author").ifPresent(author -> { + entry.getFieldOptional(FieldName.AUTHOR).ifPresent(author -> { if (!author.isEmpty()) { enhancedQuery.append('+').append(author); } }); // year - entry.getFieldOptional("year").ifPresent(year -> { + entry.getFieldOptional(FieldName.YEAR).ifPresent(year -> { if (!year.isEmpty()) { enhancedQuery.append('+').append(year); } @@ -85,7 +86,7 @@ private static String enhanceQuery(String query, BibEntry entry) { private static boolean checkValidity(BibEntry entry, JSONArray result) { // TODO: use latex-free version instead in the future - final String entryTitle = removeLaTeX(entry.getField("title")); + final String entryTitle = removeLaTeX(entry.getField(FieldName.TITLE)); // currently only title-based // title: [ "How the Mind Hurts and Heals the Body." ] @@ -93,7 +94,7 @@ private static boolean checkValidity(BibEntry entry, JSONArray result) { try { // title JSONObject data = result.getJSONObject(0); - String dataTitle = data.getJSONArray("title").getString(0); + String dataTitle = data.getJSONArray(FieldName.TITLE).getString(0); if (editDistanceIgnoreCase(entryTitle, dataTitle) <= METRIC_THRESHOLD) { return true; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java index 843b1dee3fce..1ed90271712d 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CrossrefFetcherEvaluator.java @@ -15,6 +15,7 @@ import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; /** @@ -46,7 +47,7 @@ public static void main(String[] args) throws IOException, InterruptedException @Override public void run() { - Optional origDOI = entry.getFieldOptional("doi").flatMap(DOI::build); + Optional origDOI = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); if (origDOI.isPresent()) { dois.incrementAndGet(); Optional crossrefDOI = CrossRef.findDOI(entry); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index 9634b42bef56..ed05b13c537e 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -21,6 +21,7 @@ import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -115,7 +116,7 @@ public Optional getEntryFromDOI(String doiStr, ParserResult parserResu private void formatTitleField(BibEntry entry) { // Optionally add curly brackets around key words to keep the case - entry.getFieldOptional("title").ifPresent(title -> { + entry.getFieldOptional(FieldName.TITLE).ifPresent(title -> { // Unit formatting if (Globals.prefs.getBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH)) { title = unitsToLatexFormatter.format(title); @@ -125,7 +126,7 @@ private void formatTitleField(BibEntry entry) { if (Globals.prefs.getBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH)) { title = protectTermsFormatter.format(title); } - entry.setField("title", title); + entry.setField(FieldName.TITLE, title); }); } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java index 1c77211087d4..49e91cda1c71 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java @@ -36,6 +36,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -95,7 +96,7 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint BibEntry entry = BibtexParser.singleFromString(bibtexString); if (entry != null) { // Optionally add curly brackets around key words to keep the case - entry.getFieldOptional("title").ifPresent(title -> { + entry.getFieldOptional(FieldName.TITLE).ifPresent(title -> { // Unit formatting if (Globals.prefs.getBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH)) { title = unitsToLatexFormatter.format(title); @@ -105,7 +106,7 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint if (Globals.prefs.getBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH)) { title = protectTermsFormatter.format(title); } - entry.setField("title", title); + entry.setField(FieldName.TITLE, title); }); entry.getFieldOptional("institution").ifPresent( diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java index 07eb33eb27b7..905c33fcc31c 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -13,6 +13,7 @@ import javax.xml.parsers.ParserConfigurationException; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import com.google.common.base.Strings; @@ -364,13 +365,13 @@ private BibEntry parseEntry(Element e) { // Zuordnung der Felder in Abhängigkeit vom Dokumenttyp if (author != null) { - result.setField("author", author); + result.setField(FieldName.AUTHOR, author); } if (editor != null) { - result.setField("editor", editor); + result.setField(FieldName.EDITOR, editor); } if (title != null) { - result.setField("title", title); + result.setField(FieldName.TITLE, title); } if (!Strings.isNullOrEmpty(subtitle)) { // ensure that first letter is an upper case letter @@ -384,10 +385,10 @@ private BibEntry parseEntry(Element e) { result.setField("subtitle", newSubtitle.toString()); } if (publisher != null) { - result.setField("publisher", publisher); + result.setField(FieldName.PUBLISHER, publisher); } if (year != null) { - result.setField("year", year); + result.setField(FieldName.YEAR, year); } if (address != null) { result.setField("address", address); @@ -399,38 +400,38 @@ private BibEntry parseEntry(Element e) { result.setField("edition", edition); } if (isbn != null) { - result.setField("isbn", isbn); + result.setField(FieldName.ISBN, isbn); } if (issn != null) { - result.setField("issn", issn); + result.setField(FieldName.ISSN, issn); } if (number != null) { - result.setField("number", number); + result.setField(FieldName.NUMBER, number); } if (pagetotal != null) { result.setField("pagetotal", pagetotal); } if (pages != null) { - result.setField("pages", pages); + result.setField(FieldName.PAGES, pages); } if (volume != null) { - result.setField("volume", volume); + result.setField(FieldName.VOLUME, volume); } if (journal != null) { - result.setField("journal", journal); + result.setField(FieldName.JOURNAL, journal); } if (ppn != null) { result.setField("ppn_GVK", ppn); } if (url != null) { - result.setField("url", url); + result.setField(FieldName.URL, url); } if (note != null) { result.setField("note", note); } if ("article".equals(entryType) && (journal != null)) { - result.setField("journal", journal); + result.setField(FieldName.JOURNAL, journal); } else if ("incollection".equals(entryType) && (booktitle != null)) { result.setField("booktitle", booktitle); } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java index 2a1a26934aeb..5c33925e30b9 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java @@ -42,6 +42,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -276,20 +277,20 @@ private BibEntry downloadEntry(String link) throws IOException { entry.clearField(BibEntry.KEY_FIELD); // If the entry's url field is not set, and we have stored an url for this // entry, set it: - if (!entry.hasField("url")) { + if (!entry.hasField(FieldName.URL)) { String storedUrl = entryLinks.get(link); if (storedUrl != null) { - entry.setField("url", storedUrl); + entry.setField(FieldName.URL, storedUrl); } } // Clean up some remaining HTML code from Elsevier(?) papers // Search for: Poincare algebra // to see an example - entry.getFieldOptional("title").ifPresent(title -> { + entry.getFieldOptional(FieldName.TITLE).ifPresent(title -> { String newtitle = title.replaceAll("<.?i>([^<]*)", "$1"); if (!newtitle.equals(title)) { - entry.setField("title", newtitle); + entry.setField(FieldName.TITLE, newtitle); } }); return entry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index 9d8bae307bf0..d3484928d0d3 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -48,6 +48,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -268,8 +269,8 @@ private BibEntry cleanup(BibEntry entry) { } // clean up title - if (entry.hasField("title")) { - String title = entry.getField("title"); + if (entry.hasField(FieldName.TITLE)) { + String title = entry.getField(FieldName.TITLE); // USe the alt-text and replace image links title = title.replaceAll("[ ]?img src=[^ ]+ alt=\"([^\"]+)\">[ ]?", "\\$$1\\$"); // Try to sort out most of the /spl / conversions @@ -297,12 +298,12 @@ private BibEntry cleanup(BibEntry entry) { title = protectTermsFormatter.format(title); } // Write back - entry.setField("title", title); + entry.setField(FieldName.TITLE, title); } // clean up author - if (entry.hasField("author")) { - String author = entry.getField("author"); + if (entry.hasField(FieldName.AUTHOR)) { + String author = entry.getField(FieldName.AUTHOR); author = author.replaceAll("\\s+", " "); //reorder the "Jr." "Sr." etc to the correct ordering @@ -317,11 +318,11 @@ private BibEntry cleanup(BibEntry entry) { .replace(" ,", ",").replace(" ", " "); author = author.replaceAll("[ ,;]+$", ""); //TODO: remove trailing commas - entry.setField("author", author); + entry.setField(FieldName.AUTHOR, author); } // clean up month - String month = entry.getField("month"); + String month = entry.getField(FieldName.MONTH); if ((month != null) && !month.isEmpty()) { month = month.replace(".", ""); month = month.toLowerCase(); @@ -351,18 +352,18 @@ private BibEntry cleanup(BibEntry entry) { .append(mm.group(3)).append(','); } } - entry.setField("month", date.toString()); + entry.setField(FieldName.MONTH, date.toString()); } // clean up pages - if (entry.hasField("pages")) { - String pages = entry.getField("pages"); + if (entry.hasField(FieldName.PAGES)) { + String pages = entry.getField(FieldName.PAGES); String[] pageNumbers = pages.split("-"); if (pageNumbers.length == 2) { if (pageNumbers[0].equals(pageNumbers[1])) {// single page - entry.setField("pages", pageNumbers[0]); + entry.setField(FieldName.PAGES, pageNumbers[0]); } else { - entry.setField("pages", pages.replace("-", "--")); + entry.setField(FieldName.PAGES, pages.replace("-", "--")); } } } @@ -371,7 +372,7 @@ private BibEntry cleanup(BibEntry entry) { String type = entry.getType(); String sourceField = ""; if ("article".equals(type)) { - sourceField = "journal"; + sourceField = FieldName.JOURNAL; entry.clearField("booktitle"); } else if ("inproceedings".equals(type)) { sourceField = "booktitle"; @@ -382,10 +383,10 @@ private BibEntry cleanup(BibEntry entry) { int ind = fullName.indexOf(": Accepted for future publication"); if (ind > 0) { fullName = fullName.substring(0, ind); - entry.setField("year", "to be published"); - entry.clearField("month"); - entry.clearField("pages"); - entry.clearField("number"); + entry.setField(FieldName.YEAR, "to be published"); + entry.clearField(FieldName.MONTH); + entry.clearField(FieldName.PAGES); + entry.clearField(FieldName.NUMBER); } String[] parts = fullName.split("[\\[\\]]"); //[see also...], [legacy...] fullName = parts[0]; @@ -394,10 +395,10 @@ private BibEntry cleanup(BibEntry entry) { } String note = entry.getField("note"); if ("Early Access".equals(note)) { - entry.setField("year", "to be published"); - entry.clearField("month"); - entry.clearField("pages"); - entry.clearField("number"); + entry.setField(FieldName.YEAR, "to be published"); + entry.clearField(FieldName.MONTH); + entry.clearField(FieldName.PAGES); + entry.clearField(FieldName.NUMBER); } } else { fullName = fullName.replace("Conference Proceedings", "Proceedings") @@ -471,7 +472,7 @@ private BibEntry cleanup(BibEntry entry) { fullName = fullName.trim(); fullName = fullName.replaceAll("^[tT]he ", "").replaceAll("^\\d{4} ", "").replaceAll("[,.]$", ""); - String year = entry.getField("year"); + String year = entry.getField(FieldName.YEAR); if (year != null) { fullName = fullName.replaceAll(", " + year + "\\.?", ""); } @@ -485,8 +486,8 @@ private BibEntry cleanup(BibEntry entry) { } // clean up abstract - if (entry.hasField("abstract")) { - String abstr = entry.getField("abstract"); + if (entry.hasField(FieldName.ABSTRACT)) { + String abstr = entry.getField(FieldName.ABSTRACT); // Try to sort out most of the /spl / conversions // Deal with this specific nested type first abstr = abstr.replaceAll("/sub /spl infin//", "\\$_\\\\infty\\$"); @@ -501,15 +502,15 @@ private BibEntry cleanup(BibEntry entry) { // Replace \infin with \infty abstr = abstr.replace("\\infin", "\\infty"); // Write back - entry.setField("abstract", abstr); + entry.setField(FieldName.ABSTRACT, abstr); } // Clean up url - entry.getFieldOptional("url") - .ifPresent(url -> entry.setField("url", "http://ieeexplore.ieee.org" + url.replace("tp=&", ""))); + entry.getFieldOptional(FieldName.URL) + .ifPresent(url -> entry.setField(FieldName.URL, "http://ieeexplore.ieee.org" + url.replace("tp=&", ""))); // Replace ; as keyword separator - entry.getFieldOptional("keywords").ifPresent(keys -> entry.setField("keywords", + entry.getFieldOptional(FieldName.KEYWORDS).ifPresent(keys -> entry.setField(FieldName.KEYWORDS, keys.replace(";", Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)))); return entry; } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java index 3c9949d76bc3..8cfc6a58b5b7 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java @@ -35,6 +35,7 @@ import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -90,7 +91,7 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint BibEntry entry = BibtexParser.singleFromString(bibtexString); if (entry != null) { // Optionally add curly brackets around key words to keep the case - entry.getFieldOptional("title").ifPresent(title -> { + entry.getFieldOptional(FieldName.TITLE).ifPresent(title -> { // Unit formatting if (Globals.prefs.getBoolean(JabRefPreferences.USE_UNIT_FORMATTER_ON_SEARCH)) { title = unitsToLatexFormatter.format(title); @@ -100,7 +101,7 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint if (Globals.prefs.getBoolean(JabRefPreferences.USE_CASE_KEEPER_ON_SEARCH)) { title = protectTermsFormatter.format(title); } - entry.setField("title", title); + entry.setField(FieldName.TITLE, title); }); inspector.addEntry(entry); return true; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java index e3357fe1d0ba..0ecc84b97c88 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java @@ -37,6 +37,7 @@ import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.entry.MonthUtil; @@ -206,12 +207,12 @@ public BibEntry importOai2Entry(String key) { } if (fixedKey.matches("\\d\\d\\d\\d\\..*")) { - be.setField("year", "20" + fixedKey.substring(0, 2)); + be.setField(FieldName.YEAR, "20" + fixedKey.substring(0, 2)); int monthNumber = Integer.parseInt(fixedKey.substring(2, 4)); MonthUtil.Month month = MonthUtil.getMonthByNumber(monthNumber); if (month.isValid()) { - be.setField("month", month.bibtexFormat); + be.setField(FieldName.MONTH, month.bibtexFormat); } } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java index d6fb880586e8..07422b6344a7 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java @@ -26,6 +26,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Imports a Biblioscape Tag File. The format is described on @@ -82,7 +83,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { // add item for (Map.Entry entry : lines.entrySet()) { if ("AU".equals(entry.getKey())) { - hm.put("author", entry.getValue() + hm.put(FieldName.AUTHOR, entry.getValue() .toString()); } else if ("TI".equals(entry.getKey())) { titleTI = entry.getValue() @@ -91,13 +92,13 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { titleST = entry.getValue() .toString(); } else if ("YP".equals(entry.getKey())) { - hm.put("year", entry + hm.put(FieldName.YEAR, entry .getValue().toString()); } else if ("VL".equals(entry.getKey())) { - hm.put("volume", entry + hm.put(FieldName.VOLUME, entry .getValue().toString()); } else if ("NB".equals(entry.getKey())) { - hm.put("number", entry + hm.put(FieldName.NUMBER, entry .getValue().toString()); } else if ("PS".equals(entry.getKey())) { pages[0] = entry.getValue() @@ -106,7 +107,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { pages[1] = entry.getValue() .toString(); } else if ("KW".equals(entry.getKey())) { - hm.put("keywords", entry + hm.put(FieldName.KEYWORDS, entry .getValue().toString()); } else if ("RT".equals(entry.getKey())) { type[0] = entry.getValue() @@ -121,7 +122,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { hm.put("note", entry .getValue().toString()); } else if ("PB".equals(entry.getKey())) { - hm.put("publisher", entry + hm.put(FieldName.PUBLISHER, entry .getValue().toString()); } else if ("TA".equals(entry.getKey())) { comments @@ -142,10 +143,10 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { comments .add("Quaternary Title: " + entry.getValue()); } else if ("IS".equals(entry.getKey())) { - hm.put("isbn", entry + hm.put(FieldName.ISBN, entry .getValue().toString()); } else if ("AB".equals(entry.getKey())) { - hm.put("abstract", entry + hm.put(FieldName.ABSTRACT, entry .getValue().toString()); } else if ("AD".equals(entry.getKey())) { address = entry.getValue() @@ -158,7 +159,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { .toString(); } else if ("UR".equals(entry.getKey()) || "AT".equals(entry.getKey())) { String s = entry.getValue().toString().trim(); - hm.put(s.startsWith("http://") || s.startsWith("ftp://") ? "url" + hm.put(s.startsWith("http://") || s.startsWith("ftp://") ? FieldName.URL : "pdf", entry.getValue().toString()); } else if ("C1".equals(entry.getKey())) { comments.add("Custom1: " @@ -231,17 +232,17 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { // titleTI if ("article".equals(bibtexType)) { if (titleST != null) { - hm.put("journal", titleST); + hm.put(FieldName.JOURNAL, titleST); } if (titleTI != null) { - hm.put("title", titleTI); + hm.put(FieldName.TITLE, titleTI); } } else if ("inbook".equals(bibtexType)) { if (titleST != null) { hm.put("booktitle", titleST); } if (titleTI != null) { - hm.put("title", titleTI); + hm.put(FieldName.TITLE, titleTI); } } else { if (titleST != null) { @@ -250,13 +251,13 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { // happen, I // think if (titleTI != null) { - hm.put("title", titleTI); + hm.put(FieldName.TITLE, titleTI); } } // concatenate pages if ((pages[0] != null) || (pages[1] != null)) { - hm.put("pages", (pages[0] == null ? "" : pages[0]) + (pages[1] == null ? "" : "--" + pages[1])); + hm.put(FieldName.PAGES, (pages[0] == null ? "" : pages[0]) + (pages[1] == null ? "" : "--" + pages[1])); } // concatenate address and country diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java index 9cfd91af080c..d9ec808c196f 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BibtexParser.java @@ -41,6 +41,7 @@ import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -563,7 +564,7 @@ private void parseField(BibEntry entry) throws IOException { // for users if JabRef didn't accept it. if (InternalBibtexFields.getFieldExtras(key).contains(FieldProperties.PERSON_NAMES)) { entry.setField(key, entry.getFieldOptional(key).get() + " and " + content); - } else if ("keywords".equals(key)) { + } else if (FieldName.KEYWORDS.equals(key)) { //multiple keywords fields should be combined to one entry.addKeyword(content, Globals.prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java index 2f906da50912..ded1972dc614 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java @@ -25,6 +25,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Importer for COPAC format. @@ -123,19 +124,19 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { String code = line.substring(0, 4); if ("TI- ".equals(code)) { - setOrAppend(b, "title", line.substring(4).trim(), ", "); + setOrAppend(b, FieldName.TITLE, line.substring(4).trim(), ", "); } else if ("AU- ".equals(code)) { - setOrAppend(b, "author", line.substring(4).trim(), " and "); + setOrAppend(b, FieldName.AUTHOR, line.substring(4).trim(), " and "); } else if ("PY- ".equals(code)) { - setOrAppend(b, "year", line.substring(4).trim(), ", "); + setOrAppend(b, FieldName.YEAR, line.substring(4).trim(), ", "); } else if ("PU- ".equals(code)) { - setOrAppend(b, "publisher", line.substring(4).trim(), ", "); + setOrAppend(b, FieldName.PUBLISHER, line.substring(4).trim(), ", "); } else if ("SE- ".equals(code)) { setOrAppend(b, "series", line.substring(4).trim(), ", "); } else if ("IS- ".equals(code)) { - setOrAppend(b, "isbn", line.substring(4).trim(), ", "); + setOrAppend(b, FieldName.ISBN, line.substring(4).trim(), ", "); } else if ("KW- ".equals(code)) { - setOrAppend(b, "keywords", line.substring(4).trim(), ", "); + setOrAppend(b, FieldName.KEYWORDS, line.substring(4).trim(), ", "); } else if ("NT- ".equals(code)) { setOrAppend(b, "note", line.substring(4).trim(), ", "); } else if ("PD- ".equals(code)) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java index 4ad8ca341fde..44a5b9e5a9fd 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java @@ -28,6 +28,7 @@ import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Importer for the Refer/Endnote format. @@ -148,7 +149,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { editor += " and " + val; } } else if ("T".equals(prefix)) { - hm.put("title", val); + hm.put(FieldName.TITLE, val); } else if ("0".equals(prefix)) { if (val.indexOf("Journal") == 0) { type = "article"; @@ -175,18 +176,18 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } else if ("C".equals(prefix)) { hm.put("address", val); } else if ("D".equals(prefix)) { - hm.put("year", val); + hm.put(FieldName.YEAR, val); } else if ("8".equals(prefix)) { - hm.put("date", val); + hm.put(FieldName.DATE, val); } else if ("J".equals(prefix)) { // "Alternate journal. Let's set it only if no journal // has been set with %B. - hm.putIfAbsent("journal", val); + hm.putIfAbsent(FieldName.JOURNAL, val); } else if ("B".equals(prefix)) { // This prefix stands for "journal" in a journal entry, and // "series" in a book entry. if ("article".equals(type)) { - hm.put("journal", val); + hm.put(FieldName.JOURNAL, val); } else if ("book".equals(type) || "inbook".equals(type)) { hm.put("series", val); } else { @@ -197,24 +198,24 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { if ("phdthesis".equals(type)) { hm.put("school", val); } else { - hm.put("publisher", val); + hm.put(FieldName.PUBLISHER, val); } } // replace single dash page ranges (23-45) with double dashes (23--45): else if ("P".equals(prefix)) { - hm.put("pages", val.replaceAll("([0-9]) *- *([0-9])", "$1--$2")); + hm.put(FieldName.PAGES, val.replaceAll("([0-9]) *- *([0-9])", "$1--$2")); } else if ("V".equals(prefix)) { - hm.put("volume", val); + hm.put(FieldName.VOLUME, val); } else if ("N".equals(prefix)) { - hm.put("number", val); + hm.put(FieldName.NUMBER, val); } else if ("U".equals(prefix)) { - hm.put("url", val); + hm.put(FieldName.URL, val); } else if ("R".equals(prefix)) { String doi = val; if (doi.startsWith("doi:")) { doi = doi.substring(4); } - hm.put("doi", doi); + hm.put(FieldName.DOI, doi); } else if ("O".equals(prefix)) { // Notes may contain Article number if (val.startsWith("Artn")) { @@ -224,9 +225,9 @@ else if ("P".equals(prefix)) { hm.put("note", val); } } else if ("K".equals(prefix)) { - hm.put("keywords", val); + hm.put(FieldName.KEYWORDS, val); } else if ("X".equals(prefix)) { - hm.put("abstract", val); + hm.put(FieldName.ABSTRACT, val); } else if ("9".equals(prefix)) { if (val.indexOf("Ph.D.") == 0) { type = "phdthesis"; @@ -248,14 +249,14 @@ else if ("P".equals(prefix)) { //fixauthorscomma if (!"".equals(author)) { - hm.put("author", fixAuthor(author)); + hm.put(FieldName.AUTHOR, fixAuthor(author)); } if (!"".equals(editor)) { - hm.put("editor", fixAuthor(editor)); + hm.put(FieldName.EDITOR, fixAuthor(editor)); } //if pages missing and article number given, use the article number - if (((hm.get("pages") == null) || "-".equals(hm.get("pages"))) && !"".equals(artnum)) { - hm.put("pages", artnum); + if (((hm.get(FieldName.PAGES) == null) || "-".equals(hm.get(FieldName.PAGES))) && !"".equals(artnum)) { + hm.put(FieldName.PAGES, artnum); } BibEntry b = new BibEntry(DEFAULT_BIBTEXENTRY_ID, type); // id assumes an existing database so don't diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index 445d248f21fc..35d53738b8f9 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -43,6 +43,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -152,8 +153,8 @@ public ParserResult importEntries(String text) { // current tag is either begin:author or // end:authors } - e.setField("author", sb.toString()); - } else if ("journal".equals(ln)) { + e.setField(FieldName.AUTHOR, sb.toString()); + } else if (FieldName.JOURNAL.equals(ln)) { // we guess that the entry is a journal // the alternative way is to parse // ctx:context-objects / ctx:context-object / ctx:referent / ctx:metadata-by-val / ctx:metadata / journal / rft:genre @@ -164,17 +165,17 @@ public ParserResult importEntries(String text) { } else if ("tech".equals(ln)) { type = BibtexEntryTypes.TECHREPORT; // the content of the "tech" field seems to contain the number of the technical report - e.setField("number", parser.getElementText()); - } else if ("doi".equals(ln) + e.setField(FieldName.NUMBER, parser.getElementText()); + } else if (FieldName.DOI.equals(ln) || "institution".equals(ln) || "location".equals(ln) - || "number".equals(ln) + || FieldName.NUMBER.equals(ln) || "note".equals(ln) - || "title".equals(ln) - || "pages".equals(ln) - || "publisher".equals(ln) - || "volume".equals(ln) - || "year".equals(ln)) { + || FieldName.TITLE.equals(ln) + || FieldName.PAGES.equals(ln) + || FieldName.PUBLISHER.equals(ln) + || FieldName.VOLUME.equals(ln) + || FieldName.YEAR.equals(ln)) { e.setField(ln, parser.getElementText()); } else if ("booktitle".equals(ln)) { String booktitle = parser.getElementText(); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java index 5a7887634db3..f8953eedd873 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/InspecImporter.java @@ -27,6 +27,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * INSPEC format importer. @@ -91,33 +92,33 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { String f3 = s.substring(0, 2); String frest = s.substring(5); if ("TI".equals(f3)) { - h.put("title", frest); + h.put(FieldName.TITLE, frest); } else if ("PY".equals(f3)) { - h.put("year", frest); + h.put(FieldName.YEAR, frest); } else if ("AU".equals(f3)) { - h.put("author", + h.put(FieldName.AUTHOR, AuthorList.fixAuthorLastNameFirst(frest.replace(",-", ", ").replace(";", " and "))); } else if ("AB".equals(f3)) { - h.put("abstract", frest); + h.put(FieldName.ABSTRACT, frest); } else if ("ID".equals(f3)) { - h.put("keywords", frest); + h.put(FieldName.KEYWORDS, frest); } else if ("SO".equals(f3)) { int m = frest.indexOf('.'); if (m >= 0) { String jr = frest.substring(0, m); - h.put("journal", jr.replace("-", " ")); + h.put(FieldName.JOURNAL, jr.replace("-", " ")); frest = frest.substring(m); m = frest.indexOf(';'); if (m >= 5) { String yr = frest.substring(m - 5, m).trim(); - h.put("year", yr); + h.put(FieldName.YEAR, yr); frest = frest.substring(m); m = frest.indexOf(':'); if (m >= 0) { String pg = frest.substring(m + 1).trim(); - h.put("pages", pg); + h.put(FieldName.PAGES, pg); String vol = frest.substring(1, m).trim(); - h.put("volume", vol); + h.put(FieldName.VOLUME, vol); } } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java index d61adf70c487..b1c3835b1536 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java @@ -29,6 +29,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.logic.formatter.casechanger.TitleCaseFormatter; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.MonthUtil; /** @@ -101,7 +102,7 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { public static void processSubSup(Map map) { - String[] subsup = {"title", "abstract", "review", "notes"}; + String[] subsup = {FieldName.TITLE, FieldName.ABSTRACT, FieldName.REVIEW, "notes"}; for (String aSubsup : subsup) { if (map.containsKey(aSubsup)) { @@ -132,7 +133,7 @@ public static void processSubSup(Map map) { private static void processCapitalization(Map map) { - String[] subsup = {"title", "journal", "publisher"}; + String[] subsup = {FieldName.TITLE, FieldName.JOURNAL, FieldName.PUBLISHER}; for (String aSubsup : subsup) { @@ -231,28 +232,28 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { String author = IsiImporter.isiAuthorsConvert(value.replace("EOLEOL", " and ")); // if there is already someone there then append with "and" - if (hm.get("author") != null) { - author = hm.get("author") + " and " + author; + if (hm.get(FieldName.AUTHOR) != null) { + author = hm.get(FieldName.AUTHOR) + " and " + author; } - hm.put("author", author); + hm.put(FieldName.AUTHOR, author); } else if ("TI".equals(beg)) { - hm.put("title", value.replace("EOLEOL", " ")); + hm.put(FieldName.TITLE, value.replace("EOLEOL", " ")); } else if ("SO".equals(beg) || "JA".equals(beg)) { - hm.put("journal", value.replace("EOLEOL", " ")); + hm.put(FieldName.JOURNAL, value.replace("EOLEOL", " ")); } else if ("ID".equals(beg) || "KW".equals(beg)) { value = value.replace("EOLEOL", " "); - String existingKeywords = hm.get("keywords"); + String existingKeywords = hm.get(FieldName.KEYWORDS); if ((existingKeywords == null) || existingKeywords.contains(value)) { existingKeywords = value; } else { existingKeywords += ", " + value; } - hm.put("keywords", existingKeywords); + hm.put(FieldName.KEYWORDS, existingKeywords); } else if ("AB".equals(beg)) { - hm.put("abstract", value.replace("EOLEOL", " ")); + hm.put(FieldName.ABSTRACT, value.replace("EOLEOL", " ")); } else if ("BP".equals(beg) || "BR".equals(beg) || "SP".equals(beg)) { pages = value; } else if ("EP".equals(beg)) { @@ -269,20 +270,20 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } else if ("AR".equals(beg)) { pages = value; } else if ("IS".equals(beg)) { - hm.put("number", value); + hm.put(FieldName.NUMBER, value); } else if ("PY".equals(beg)) { - hm.put("year", value); + hm.put(FieldName.YEAR, value); } else if ("VL".equals(beg)) { - hm.put("volume", value); + hm.put(FieldName.VOLUME, value); } else if ("PU".equals(beg)) { - hm.put("publisher", value); + hm.put(FieldName.PUBLISHER, value); } else if ("DI".equals(beg)) { - hm.put("doi", value); + hm.put(FieldName.DOI, value); } else if ("PD".equals(beg)) { String month = IsiImporter.parseMonth(value); if (month != null) { - hm.put("month", month); + hm.put(FieldName.MONTH, month); } } else if ("DT".equals(beg)) { @@ -306,7 +307,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } if (!"".equals(pages)) { - hm.put("pages", pages); + hm.put(FieldName.PAGES, pages); } // Skip empty entries diff --git a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java index 134501c69f47..badc3fdb7667 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java @@ -22,6 +22,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.MonthUtil; import net.sf.jabref.preferences.JabRefPreferences; @@ -42,10 +43,10 @@ public class JSONEntryParser { */ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { // Fields that are directly accessible at the top level BibJson object - String[] singleFieldStrings = {"year", "title", "abstract", "month"}; + String[] singleFieldStrings = {FieldName.YEAR, FieldName.TITLE, FieldName.ABSTRACT, FieldName.MONTH}; // Fields that are accessible in the journal part of the BibJson object - String[] journalSingleFieldStrings = {"publisher", "number", "volume"}; + String[] journalSingleFieldStrings = {FieldName.PUBLISHER, FieldName.NUMBER, FieldName.VOLUME}; @@ -63,7 +64,7 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { LOGGER.info("Empty author name."); } } - entry.setField("author", String.join(" and ", authorList)); + entry.setField(FieldName.AUTHOR, String.join(" and ", authorList)); } else { LOGGER.info("No author found."); } @@ -78,10 +79,10 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { // Page numbers if (bibJsonEntry.has("start_page")) { if (bibJsonEntry.has("end_page")) { - entry.setField("pages", + entry.setField(FieldName.PAGES, bibJsonEntry.getString("start_page") + "--" + bibJsonEntry.getString("end_page")); } else { - entry.setField("pages", bibJsonEntry.getString("start_page")); + entry.setField(FieldName.PAGES, bibJsonEntry.getString("start_page")); } } @@ -90,7 +91,7 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { JSONObject journal = bibJsonEntry.getJSONObject("journal"); // Journal title if (journal.has("title")) { - entry.setField("journal", journal.getString("title")); + entry.setField(FieldName.JOURNAL, journal.getString("title")); } else { LOGGER.info("No journal title found."); } @@ -122,11 +123,11 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { for (int i = 0; i < identifiers.length(); i++) { String type = identifiers.getJSONObject(i).getString("type"); if ("doi".equals(type)) { - entry.setField("doi", identifiers.getJSONObject(i).getString("id")); + entry.setField(FieldName.DOI, identifiers.getJSONObject(i).getString("id")); } else if ("pissn".equals(type)) { - entry.setField("issn", identifiers.getJSONObject(i).getString("id")); + entry.setField(FieldName.ISSN, identifiers.getJSONObject(i).getString("id")); } else if ("eissn".equals(type)) { - entry.setField("issn", identifiers.getJSONObject(i).getString("id")); + entry.setField(FieldName.ISSN, identifiers.getJSONObject(i).getString("id")); } } } @@ -138,7 +139,7 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { if (links.getJSONObject(i).has("type")) { String type = links.getJSONObject(i).getString("type"); if ("fulltext".equals(type) && links.getJSONObject(i).has("url")) { - entry.setField("url", links.getJSONObject(i).getString("url")); + entry.setField(FieldName.URL, links.getJSONObject(i).getString("url")); } } } @@ -155,8 +156,8 @@ public BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry) { */ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { // Fields that are directly accessible at the top level Json object - String[] singleFieldStrings = {"issn", "volume", "abstract", "doi", "title", "number", - "publisher"}; + String[] singleFieldStrings = {FieldName.ISSN, FieldName.VOLUME, FieldName.ABSTRACT, FieldName.DOI, FieldName.TITLE, FieldName.NUMBER, + FieldName.PUBLISHER}; BibEntry entry = new BibEntry(); String nametype; @@ -166,12 +167,12 @@ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { if (com.google.common.base.Strings.isNullOrEmpty(isbn)) { // Probably article entry.setType("article"); - nametype = "journal"; + nametype = FieldName.JOURNAL; } else { // Probably book chapter or from proceeding, go for book chapter entry.setType("incollection"); nametype = "booktitle"; - entry.setField("isbn", isbn); + entry.setField(FieldName.ISBN, isbn); } // Authors @@ -185,7 +186,7 @@ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { LOGGER.info("Empty author name."); } } - entry.setField("author", String.join(" and ", authorList)); + entry.setField(FieldName.AUTHOR, String.join(" and ", authorList)); } else { LOGGER.info("No author found."); } @@ -203,10 +204,10 @@ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { // Page numbers if (springerJsonEntry.has("startingPage") && !(springerJsonEntry.getString("startingPage").isEmpty())) { if (springerJsonEntry.has("endPage") && !(springerJsonEntry.getString("endPage").isEmpty())) { - entry.setField("pages", + entry.setField(FieldName.PAGES, springerJsonEntry.getString("startingPage") + "--" + springerJsonEntry.getString("endPage")); } else { - entry.setField("pages", springerJsonEntry.getString("startingPage")); + entry.setField(FieldName.PAGES, springerJsonEntry.getString("startingPage")); } } @@ -219,25 +220,25 @@ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { if (springerJsonEntry.has("url")) { JSONArray urlarray = springerJsonEntry.optJSONArray("url"); if (urlarray == null) { - entry.setField("url", springerJsonEntry.optString("url")); + entry.setField(FieldName.URL, springerJsonEntry.optString("url")); } else { - entry.setField("url", urlarray.getJSONObject(0).optString("value")); + entry.setField(FieldName.URL, urlarray.getJSONObject(0).optString("value")); } } // Date if (springerJsonEntry.has("publicationDate")) { String date = springerJsonEntry.getString("publicationDate"); - entry.setField("date", date); // For BibLatex + entry.setField(FieldName.DATE, date); // For BibLatex String[] dateparts = date.split("-"); - entry.setField("year", dateparts[0]); - entry.setField("month", MonthUtil.getMonthByNumber(Integer.parseInt(dateparts[1])).bibtexFormat); + entry.setField(FieldName.YEAR, dateparts[0]); + entry.setField(FieldName.MONTH, MonthUtil.getMonthByNumber(Integer.parseInt(dateparts[1])).bibtexFormat); } // Clean up abstract (often starting with Abstract) - entry.getFieldOptional("abstract").ifPresent(abstractContents -> { + entry.getFieldOptional(FieldName.ABSTRACT).ifPresent(abstractContents -> { if (abstractContents.startsWith("Abstract")) { - entry.setField("abstract", abstractContents.substring(8)); + entry.setField(FieldName.ABSTRACT, abstractContents.substring(8)); } }); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index f6da32045770..a73dfed8f79a 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -31,6 +31,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Importer for the MEDLINE Plain format. @@ -155,11 +156,11 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { //store the fields in a map Map hashMap = new HashMap<>(); - hashMap.put("PG", "pages"); + hashMap.put("PG", FieldName.PAGES); hashMap.put("PL", "address"); hashMap.put("PHST", "history"); hashMap.put("PST", "publication-status"); - hashMap.put("VI", "volume"); + hashMap.put("VI", FieldName.VOLUME); hashMap.put("LA", "language"); hashMap.put("LA", "language"); hashMap.put("PUBM", "model"); @@ -167,7 +168,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { hashMap.put("NM", "substance-name"); hashMap.put("OCI", "copyright-owner"); hashMap.put("CN", "corporate"); - hashMap.put("IP", "issue"); + hashMap.put("IP", FieldName.ISSUE); hashMap.put("EN", "edition"); hashMap.put("GS", "gene-symbol"); hashMap.put("GN", "note"); @@ -197,11 +198,11 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { fields.put("investigator", oldInvestigator + ", " + value); } } else if ("MH".equals(label) || "OT".equals(label)) { - if (!fields.containsKey("keywords")) { - fields.put("keywords", value); + if (!fields.containsKey(FieldName.KEYWORDS)) { + fields.put(FieldName.KEYWORDS, value); } else { - String kw = fields.get("keywords"); - fields.put("keywords", kw + ", " + value); + String kw = fields.get(FieldName.KEYWORDS); + fields.put(FieldName.KEYWORDS, kw + ", " + value); } } else if ("CON".equals(label) || "CIN".equals(label) || "EIN".equals(label) || "EFR".equals(label) || "CRI".equals(label) || "CRF".equals(label) || "PRIN".equals(label) || "PROF".equals(label) @@ -213,8 +214,8 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { comment = comment + value; } } - fixAuthors(fields, author, "author"); - fixAuthors(fields, editor, "editor"); + fixAuthors(fields, author, FieldName.AUTHOR); + fixAuthors(fields, editor, FieldName.EDITOR); if (!comment.isEmpty()) { fields.put("comment", comment); } @@ -274,7 +275,7 @@ private String addSourceType(String value, String type) { private void addStandardNumber(Map hm, String lab, String value) { if ("IS".equals(lab)) { - String key = "issn"; + String key = FieldName.ISSN; //it is possible to have two issn, one for electronic and for print //if there are two then it comes at the end in brackets (electronic) or (print) //so search for the brackets @@ -288,7 +289,7 @@ private void addStandardNumber(Map hm, String lab, String value) hm.put(key, value); } } else if ("ISBN".equals(lab)) { - hm.put("isbn", value); + hm.put(FieldName.ISBN, value); } } @@ -305,7 +306,7 @@ private void addIDs(Map hm, String lab, String value) { String idValue = value; if (value.startsWith("doi:")) { idValue = idValue.replaceAll("(?i)doi:", "").trim(); - key = "doi"; + key = FieldName.DOI; } else if (value.indexOf('[') > 0) { int startOfIdentifier = value.indexOf('['); int endOfIdentifier = value.indexOf(']'); @@ -329,14 +330,14 @@ private void addIDs(Map hm, String lab, String value) { private void addTitles(Map hm, String lab, String val, String type) { if ("TI".equals(lab)) { - String oldVal = hm.get("title"); + String oldVal = hm.get(FieldName.TITLE); if (oldVal == null) { - hm.put("title", val); + hm.put(FieldName.TITLE, val); } else { if (oldVal.endsWith(":") || oldVal.endsWith(".") || oldVal.endsWith("?")) { - hm.put("title", oldVal + " " + val); + hm.put(FieldName.TITLE, oldVal + " " + val); } else { - hm.put("title", oldVal + ": " + val); + hm.put(FieldName.TITLE, oldVal + ": " + val); } } } else if ("BTI".equals(lab) || "CTI".equals(lab)) { @@ -345,7 +346,7 @@ private void addTitles(Map hm, String lab, String val, String ty if ("inproceedings".equals(type)) { hm.put("booktitle", val); } else { - hm.put("journal", val); + hm.put(FieldName.JOURNAL, val); } } else if ("CTI".equals(lab)) { hm.put("collection-title", val); @@ -371,11 +372,11 @@ private void addAbstract(Map hm, String lab, String value) { } else { abstractValue = value; } - String oldAb = hm.get("abstract"); + String oldAb = hm.get(FieldName.ABSTRACT); if (oldAb == null) { - hm.put("abstract", abstractValue); + hm.put(FieldName.ABSTRACT, abstractValue); } else { - hm.put("abstract", oldAb + Globals.NEWLINE + abstractValue); + hm.put(FieldName.ABSTRACT, oldAb + Globals.NEWLINE + abstractValue); } } else if ("OAB".equals(lab) || "OABL".equals(lab)) { hm.put("other-abstract", value); @@ -395,9 +396,9 @@ private void addDates(Map hm, String lab, String val) { hm.put("revised", val); } else if ("DP".equals(lab)) { String[] parts = val.split(" "); - hm.put("year", parts[0]); + hm.put(FieldName.YEAR, parts[0]); if ((parts.length > 1) && !parts[1].isEmpty()) { - hm.put("month", parts[1]); + hm.put(FieldName.MONTH, parts[1]); } } else if ("EDAT".equals(lab) && isCreateDateFormat(val)) { hm.put("publication", val); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java index 9d4ebebde68b..32689b7d4ce0 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java @@ -28,6 +28,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; /** @@ -120,59 +121,59 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } if (isAuthor) { - h.put("author", content); + h.put(FieldName.AUTHOR, content); } else if (fieldName.startsWith("Title")) { content = content.replaceAll("\\[.+\\]", "").trim(); if (content.endsWith(".")) { content = content.substring(0, content.length() - 1); } - h.put("title", content); + h.put(FieldName.TITLE, content); } else if (fieldName.startsWith("Chapter Title")) { h.put("chaptertitle", content); } else if (fieldName.startsWith("Source")) { Matcher matcher; if ((matcher = OvidImporter.OVID_SOURCE_PATTERN.matcher(content)).find()) { - h.put("journal", matcher.group(1)); - h.put("volume", matcher.group(2)); - h.put("issue", matcher.group(3)); - h.put("pages", matcher.group(4)); - h.put("year", matcher.group(5)); + h.put(FieldName.JOURNAL, matcher.group(1)); + h.put(FieldName.VOLUME, matcher.group(2)); + h.put(FieldName.ISSUE, matcher.group(3)); + h.put(FieldName.PAGES, matcher.group(4)); + h.put(FieldName.YEAR, matcher.group(5)); } else if ((matcher = OvidImporter.OVID_SOURCE_PATTERN_NO_ISSUE.matcher(content)).find()) {// may be missing the issue - h.put("journal", matcher.group(1)); - h.put("volume", matcher.group(2)); - h.put("pages", matcher.group(3)); - h.put("year", matcher.group(4)); + h.put(FieldName.JOURNAL, matcher.group(1)); + h.put(FieldName.VOLUME, matcher.group(2)); + h.put(FieldName.PAGES, matcher.group(3)); + h.put(FieldName.YEAR, matcher.group(4)); } else if ((matcher = OvidImporter.OVID_SOURCE_PATTERN_2.matcher(content)).find()) { - h.put("journal", matcher.group(1)); - h.put("volume", matcher.group(2)); - h.put("issue", matcher.group(3)); - h.put("month", matcher.group(4)); - h.put("year", matcher.group(5)); - h.put("pages", matcher.group(6)); + h.put(FieldName.JOURNAL, matcher.group(1)); + h.put(FieldName.VOLUME, matcher.group(2)); + h.put(FieldName.ISSUE, matcher.group(3)); + h.put(FieldName.MONTH, matcher.group(4)); + h.put(FieldName.YEAR, matcher.group(5)); + h.put(FieldName.PAGES, matcher.group(6)); } else if ((matcher = OvidImporter.INCOLLECTION_PATTERN.matcher(content)).find()) { - h.put("editor", matcher.group(1).replace(" (Ed)", "")); - h.put("year", matcher.group(2)); + h.put(FieldName.EDITOR, matcher.group(1).replace(" (Ed)", "")); + h.put(FieldName.YEAR, matcher.group(2)); h.put("booktitle", matcher.group(3)); - h.put("pages", matcher.group(4)); + h.put(FieldName.PAGES, matcher.group(4)); h.put("address", matcher.group(5)); - h.put("publisher", matcher.group(6)); + h.put(FieldName.PUBLISHER, matcher.group(6)); } else if ((matcher = OvidImporter.BOOK_PATTERN.matcher(content)).find()) { - h.put("year", matcher.group(1)); - h.put("pages", matcher.group(2)); + h.put(FieldName.YEAR, matcher.group(1)); + h.put(FieldName.PAGES, matcher.group(2)); h.put("address", matcher.group(3)); - h.put("publisher", matcher.group(4)); + h.put(FieldName.PUBLISHER, matcher.group(4)); } // Add double hyphens to page ranges: - if (h.get("pages") != null) { - h.put("pages", h.get("pages").replace("-", "--")); + if (h.get(FieldName.PAGES) != null) { + h.put(FieldName.PAGES, h.get(FieldName.PAGES).replace("-", "--")); } } else if ("Abstract".equals(fieldName)) { - h.put("abstract", content); + h.put(FieldName.ABSTRACT, content); } else if ("Publication Type".equals(fieldName)) { if (content.contains("Book")) { @@ -186,30 +187,30 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { h.put("language", content); } else if (fieldName.startsWith("Author Keywords")) { content = content.replace(";", ",").replace(" ", " "); - h.put("keywords", content); + h.put(FieldName.KEYWORDS, content); } else if (fieldName.startsWith("ISSN")) { - h.put("issn", content); + h.put(FieldName.ISSN, content); } else if (fieldName.startsWith("DOI Number")) { - h.put("doi", content); + h.put(FieldName.DOI, content); } } // Now we need to check if a book entry has given editors in the author field; // if so, rearrange: - String auth = h.get("author"); + String auth = h.get(FieldName.AUTHOR); if ((auth != null) && auth.contains(" [Ed]")) { - h.remove("author"); - h.put("editor", auth.replace(" [Ed]", "")); + h.remove(FieldName.AUTHOR); + h.put(FieldName.EDITOR, auth.replace(" [Ed]", "")); } // Rearrange names properly: - auth = h.get("author"); + auth = h.get(FieldName.AUTHOR); if (auth != null) { - h.put("author", fixNames(auth)); + h.put(FieldName.AUTHOR, fixNames(auth)); } - auth = h.get("editor"); + auth = h.get(FieldName.EDITOR); if (auth != null) { - h.put("editor", fixNames(auth)); + h.put(FieldName.EDITOR, fixNames(auth)); } // Set the entrytype properly: @@ -219,7 +220,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { // This means we have an "incollection" entry. entryType = "incollection"; // Move the "chaptertitle" to just "title": - h.put("title", h.remove("chaptertitle")); + h.put(FieldName.TITLE, h.remove("chaptertitle")); } BibEntry b = new BibEntry(IdGenerator.next(), entryType); b.setField(h); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index 069899118347..97ac6e5b8163 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -37,6 +37,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import com.google.common.base.Strings; import org.apache.pdfbox.pdmodel.PDDocument; @@ -389,7 +390,7 @@ public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { if (DOI == null) { pos = curString.indexOf("DOI"); if (pos < 0) { - pos = curString.indexOf("doi"); + pos = curString.indexOf(FieldName.DOI); } if (pos >= 0) { pos += 3; @@ -442,43 +443,43 @@ public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { // TODO: institution parsing missing if (author != null) { - entry.setField("author", author); + entry.setField(FieldName.AUTHOR, author); } if (editor != null) { - entry.setField("editor", editor); + entry.setField(FieldName.EDITOR, editor); } if (abstractT != null) { - entry.setField("abstract", abstractT); + entry.setField(FieldName.ABSTRACT, abstractT); } if (!Strings.isNullOrEmpty(keywords)) { - entry.setField("keywords", keywords); + entry.setField(FieldName.KEYWORDS, keywords); } if (title != null) { - entry.setField("title", title); + entry.setField(FieldName.TITLE, title); } if (conference != null) { entry.setField("booktitle", conference); } if (DOI != null) { - entry.setField("doi", DOI); + entry.setField(FieldName.DOI, DOI); } if (series != null) { entry.setField("series", series); } if (volume != null) { - entry.setField("volume", volume); + entry.setField(FieldName.VOLUME, volume); } if (number != null) { - entry.setField("number", number); + entry.setField(FieldName.NUMBER, number); } if (pages != null) { - entry.setField("pages", pages); + entry.setField(FieldName.PAGES, pages); } if (year != null) { - entry.setField("year", year); + entry.setField(FieldName.YEAR, year); } if (publisher != null) { - entry.setField("publisher", publisher); + entry.setField(FieldName.PUBLISHER, publisher); } result.add(entry); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index 31e7881705e8..89ba9e6f3827 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -35,6 +35,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.preferences.JabRefPreferences; @@ -255,7 +256,7 @@ private String readMultipleLines(BufferedReader in) throws IOException { private void parseTitleString(BibEntry be, BufferedReader in) throws IOException { // skip article number this.lastLine = this.lastLine.substring(this.lastLine.indexOf('.') + 1, this.lastLine.length()); - be.setField("title", readMultipleLines(in)); + be.setField(FieldName.TITLE, readMultipleLines(in)); } /** @@ -305,7 +306,7 @@ private void parseAuthors(BibEntry be, BufferedReader in) throws IOException { } if (!authors.isEmpty()) { - be.setField("author", String.join(" and ", authors)); + be.setField(FieldName.AUTHOR, String.join(" and ", authors)); } if (institutions.length() > 0) { be.setField("institution", institutions.toString()); @@ -322,7 +323,7 @@ private void parseAbstract(BibEntry be, BufferedReader in) throws IOException { String theabstract = readMultipleLines(in); if (!"".equals(theabstract)) { - be.setField("abstract", theabstract); + be.setField(FieldName.ABSTRACT, theabstract); } } @@ -374,9 +375,9 @@ private void parseAdditionalFields(BibEntry be, boolean multilineUrlFieldAllowed Calendar cal = new GregorianCalendar(); cal.setTime(date == null ? new Date() : date); - be.setField("year", String.valueOf(cal.get(Calendar.YEAR))); + be.setField(FieldName.YEAR, String.valueOf(cal.get(Calendar.YEAR))); if ((date != null) && recognizedDateFormats[i - 1].contains("MM")) { - be.setField("month", String.valueOf(cal.get(Calendar.MONTH) + 1)); + be.setField(FieldName.MONTH, String.valueOf(cal.get(Calendar.MONTH) + 1)); } if ((date != null) && recognizedDateFormats[i - 1].contains("dd")) { be.setField("day", String.valueOf(cal.get(Calendar.DAY_OF_MONTH))); @@ -391,7 +392,7 @@ private void parseAdditionalFields(BibEntry be, boolean multilineUrlFieldAllowed content = this.lastLine; readLine(in); } - be.setField("url", content); + be.setField(FieldName.URL, content); // authors field } else if (keyword.startsWith("By")) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java index 1863dc617a76..29c10eaffc26 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java @@ -28,6 +28,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.MonthUtil; /** @@ -134,17 +135,17 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { type = "other"; } } else if ("T1".equals(lab) || "TI".equals(lab)) { - String oldVal = hm.get("title"); + String oldVal = hm.get(FieldName.TITLE); if (oldVal == null) { - hm.put("title", val); + hm.put(FieldName.TITLE, val); } else { if (oldVal.endsWith(":") || oldVal.endsWith(".") || oldVal.endsWith("?")) { - hm.put("title", oldVal + " " + val); + hm.put(FieldName.TITLE, oldVal + " " + val); } else { - hm.put("title", oldVal + ": " + val); + hm.put(FieldName.TITLE, oldVal + ": " + val); } } - hm.put("title", hm.get("title").replaceAll("\\s+", " ")); // Normalize whitespaces + hm.put(FieldName.TITLE, hm.get(FieldName.TITLE).replaceAll("\\s+", " ")); // Normalize whitespaces } else if ("T2".equals(lab) || "BT".equals(lab)) { hm.put("booktitle", val); } else if ("T3".equals(lab)) { @@ -165,7 +166,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { if ("inproceedings".equals(type)) { hm.put("booktitle", val); } else { - hm.put("journal", val); + hm.put(FieldName.JOURNAL, val); } } else if ("SP".equals(lab)) { startPage = val; @@ -173,7 +174,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { if ("phdthesis".equals(type)) { hm.put("school", val); } else { - hm.put("publisher", val); + hm.put(FieldName.PUBLISHER, val); } } else if ("AD".equals(lab) || "CY".equals(lab)) { hm.put("address", val); @@ -183,41 +184,41 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { endPage = "--" + endPage; } } else if ("SN".equals(lab)) { - hm.put("issn", val); + hm.put(FieldName.ISSN, val); } else if ("VL".equals(lab)) { - hm.put("volume", val); + hm.put(FieldName.VOLUME, val); } else if ("IS".equals(lab)) { - hm.put("number", val); + hm.put(FieldName.NUMBER, val); } else if ("N2".equals(lab) || "AB".equals(lab)) { - String oldAb = hm.get("abstract"); + String oldAb = hm.get(FieldName.ABSTRACT); if (oldAb == null) { - hm.put("abstract", val); + hm.put(FieldName.ABSTRACT, val); } else { - hm.put("abstract", oldAb + Globals.NEWLINE + val); + hm.put(FieldName.ABSTRACT, oldAb + Globals.NEWLINE + val); } } else if ("UR".equals(lab)) { - hm.put("url", val); + hm.put(FieldName.URL, val); } else if (("Y1".equals(lab) || "PY".equals(lab)) && (val.length() >= 4)) { String[] parts = val.split("/"); - hm.put("year", parts[0]); + hm.put(FieldName.YEAR, parts[0]); if ((parts.length > 1) && !parts[1].isEmpty()) { try { int monthNumber = Integer.parseInt(parts[1]); MonthUtil.Month month = MonthUtil.getMonthByNumber(monthNumber); if (month.isValid()) { - hm.put("month", month.bibtexFormat); + hm.put(FieldName.MONTH, month.bibtexFormat); } } catch (NumberFormatException ex) { // The month part is unparseable, so we ignore it. } } } else if ("KW".equals(lab)) { - if (hm.containsKey("keywords")) { - String kw = hm.get("keywords"); - hm.put("keywords", kw + ", " + val); + if (hm.containsKey(FieldName.KEYWORDS)) { + String kw = hm.get(FieldName.KEYWORDS); + hm.put(FieldName.KEYWORDS, kw + ", " + val); } else { - hm.put("keywords", val); + hm.put(FieldName.KEYWORDS, val); } } else if ("U1".equals(lab) || "U2".equals(lab) || "N1".equals(lab)) { if (!comment.isEmpty()) { @@ -232,24 +233,24 @@ else if ("ID".equals(lab)) { String doi = val; if (doi.startsWith("doi:")) { doi = doi.replaceAll("(?i)doi:", "").trim(); - hm.put("doi", doi); + hm.put(FieldName.DOI, doi); } } } // fix authors if (!author.isEmpty()) { author = AuthorList.fixAuthorLastNameFirst(author); - hm.put("author", author); + hm.put(FieldName.AUTHOR, author); } if (!editor.isEmpty()) { editor = AuthorList.fixAuthorLastNameFirst(editor); - hm.put("editor", editor); + hm.put(FieldName.EDITOR, editor); } if (!comment.isEmpty()) { hm.put("comment", comment); } - hm.put("pages", startPage + endPage); + hm.put(FieldName.PAGES, startPage + endPage); } BibEntry b = new BibEntry(DEFAULT_BIBTEXENTRY_ID, type); // id assumes an existing database so don't diff --git a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java index 37a7060f98af..e0db96ec5a77 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java @@ -27,6 +27,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Imports a SilverPlatter exported file. This is a poor format to parse, @@ -100,41 +101,41 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { String f3 = field.substring(0, 2); String frest = field.substring(5); if ("TI".equals(f3)) { - h.put("title", frest); + h.put(FieldName.TITLE, frest); } else if ("AU".equals(f3)) { if (frest.trim().endsWith("(ed)")) { String ed = frest.trim(); ed = ed.substring(0, ed.length() - 4); - h.put("editor", + h.put(FieldName.EDITOR, AuthorList.fixAuthorLastNameFirst(ed.replace(",-", ", ").replace(";", " and "))); } else { - h.put("author", + h.put(FieldName.AUTHOR, AuthorList.fixAuthorLastNameFirst(frest.replace(",-", ", ").replace(";", " and "))); } } else if ("AB".equals(f3)) { - h.put("abstract", frest); + h.put(FieldName.ABSTRACT, frest); } else if ("DE".equals(f3)) { String kw = frest.replace("-;", ",").toLowerCase(); - h.put("keywords", kw.substring(0, kw.length() - 1)); + h.put(FieldName.KEYWORDS, kw.substring(0, kw.length() - 1)); } else if ("SO".equals(f3)) { int m = frest.indexOf('.'); if (m >= 0) { String jr = frest.substring(0, m); - h.put("journal", jr.replace("-", " ")); + h.put(FieldName.JOURNAL, jr.replace("-", " ")); frest = frest.substring(m); m = frest.indexOf(';'); if (m >= 5) { String yr = frest.substring(m - 5, m).trim(); - h.put("year", yr); + h.put(FieldName.YEAR, yr); frest = frest.substring(m); m = frest.indexOf(':'); int issueIndex = frest.indexOf('('); int endIssueIndex = frest.indexOf(')'); if (m >= 0) { String pg = frest.substring(m + 1).trim(); - h.put("pages", pg); - h.put("volume", frest.substring(1, issueIndex).trim()); - h.put("issue", frest.substring(issueIndex + 1, endIssueIndex).trim()); + h.put(FieldName.PAGES, pg); + h.put(FieldName.VOLUME, frest.substring(1, issueIndex).trim()); + h.put(FieldName.ISSUE, frest.substring(issueIndex + 1, endIssueIndex).trim()); } } } @@ -142,14 +143,14 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { int m = frest.indexOf(':'); if (m >= 0) { String jr = frest.substring(0, m); - h.put("publisher", jr.replace("-", " ").trim()); + h.put(FieldName.PUBLISHER, jr.replace("-", " ").trim()); frest = frest.substring(m); m = frest.indexOf(", "); if ((m + 2) < frest.length()) { String yr = frest.substring(m + 2).trim(); try { Integer.parseInt(yr); - h.put("year", yr); + h.put(FieldName.YEAR, yr); } catch (NumberFormatException ex) { // Let's assume that this wasn't a number, since it // couldn't be parsed as an integer. @@ -167,7 +168,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { type = "book"; } else if (frest.startsWith("Dissertation")) { type = "phdthesis"; - } else if (frest.toLowerCase().contains("journal")) { + } else if (frest.toLowerCase().contains(FieldName.JOURNAL)) { type = "article"; } else if ("Contribution".equals(frest) || "Chapter".equals(frest)) { type = "incollection"; @@ -181,12 +182,12 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } if (isChapter) { - Object titleO = h.get("title"); + Object titleO = h.get(FieldName.TITLE); if (titleO != null) { String title = ((String) titleO).trim(); int inPos = title.indexOf("\" in "); if (inPos > 1) { - h.put("title", title.substring(0, inPos)); + h.put(FieldName.TITLE, title.substring(0, inPos)); } } diff --git a/src/main/java/net/sf/jabref/logic/TypedBibEntry.java b/src/main/java/net/sf/jabref/logic/TypedBibEntry.java index b3bc4898d30f..e684e00d8998 100644 --- a/src/main/java/net/sf/jabref/logic/TypedBibEntry.java +++ b/src/main/java/net/sf/jabref/logic/TypedBibEntry.java @@ -21,7 +21,6 @@ import java.util.Optional; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.Globals; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; @@ -29,6 +28,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; @@ -88,7 +88,7 @@ public String getTypeForDisplay() { */ public List getFiles() { //Extract the path - Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + Optional oldValue = entry.getFieldOptional(FieldName.FILE); if (!oldValue.isPresent()) { return new ArrayList<>(); } @@ -98,14 +98,14 @@ public List getFiles() { public Optional setFiles(List files) { - Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + Optional oldValue = entry.getFieldOptional(FieldName.FILE); String newValue = FileField.getStringRepresentation(files); if(oldValue.isPresent() && oldValue.get().equals(newValue)) { return Optional.empty(); } - entry.setField(Globals.FILE_FIELD, newValue); - return Optional.of(new FieldChange(entry, Globals.FILE_FIELD, oldValue.orElse(""), newValue)); + entry.setField(FieldName.FILE, newValue); + return Optional.of(new FieldChange(entry, FieldName.FILE, oldValue.orElse(""), newValue)); } } diff --git a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java index 1089cc36eeea..fbe937b70dbe 100644 --- a/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java +++ b/src/main/java/net/sf/jabref/logic/autocompleter/AutoCompleterFactory.java @@ -19,6 +19,7 @@ import java.util.Objects; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -43,9 +44,9 @@ public AutoCompleter getFor(String fieldName) { if (InternalBibtexFields.getFieldExtras(fieldName).contains(FieldProperties.PERSON_NAMES)) { return new NameFieldAutoCompleter(fieldName, preferences); - } else if ("crossref".equals(fieldName)) { + } else if (FieldName.CROSSREF.equals(fieldName)) { return new BibtexKeyAutoCompleter(preferences); - } else if ("journal".equals(fieldName) || "publisher".equals(fieldName)) { + } else if (FieldName.JOURNAL.equals(fieldName) || FieldName.PUBLISHER.equals(fieldName)) { return new JournalAutoCompleter(fieldName, preferences, abbreviationLoader); } else { return new DefaultAutoCompleter(fieldName, preferences); @@ -53,7 +54,7 @@ public AutoCompleter getFor(String fieldName) { } public AutoCompleter getPersonAutoCompleter() { - return new NameFieldAutoCompleter(Arrays.asList("author", "editor"), true, preferences); + return new NameFieldAutoCompleter(Arrays.asList(FieldName.AUTHOR, FieldName.EDITOR), true, preferences); } } diff --git a/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java b/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java index 0c3778fe4d81..f59a8774734d 100644 --- a/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java +++ b/src/main/java/net/sf/jabref/logic/auxparser/AuxParser.java @@ -14,6 +14,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import org.apache.commons.logging.Log; @@ -148,7 +149,7 @@ private void resolveTags(AuxParserResult result) { * Resolves and adds CrossRef entries */ private void resolveCrossReferences(BibEntry entry, AuxParserResult result) { - entry.getFieldOptional("crossref").ifPresent(crossref -> { + entry.getFieldOptional(FieldName.CROSSREF).ifPresent(crossref -> { if (!result.getUniqueKeys().contains(crossref)) { Optional refEntry = masterDatabase.getEntryByKey(crossref); diff --git a/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java index dc3492095369..a11493a987fc 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/BibEntryWriter.java @@ -159,7 +159,7 @@ private void writeField(BibEntry entry, Writer out, String name, int indentation } private int getLengthOfLongestFieldName(BibEntry entry) { - Predicate isNotBibtexKey = field -> !"bibtexkey".equals(field); + Predicate isNotBibtexKey = field -> !BibEntry.KEY_FIELD.equals(field); return entry.getFieldNames().stream().filter(isNotBibtexKey).mapToInt(String::length).max().orElse(0); } diff --git a/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java index a363afc295f2..982c6049789a 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/FieldContentParser.java @@ -19,6 +19,7 @@ import java.util.regex.Pattern; import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.entry.FieldName; /** * This class provides the reformatting needed when reading BibTeX fields formatted @@ -35,8 +36,8 @@ public class FieldContentParser { public FieldContentParser(FieldContentParserPreferences prefs) { multiLineFields = new HashSet<>(); // the following two are also coded in net.sf.jabref.logic.bibtex.LatexFieldFormatter.format(String, String) - multiLineFields.add("abstract"); - multiLineFields.add("review"); + multiLineFields.add(FieldName.ABSTRACT); + multiLineFields.add(FieldName.REVIEW); // the file field should not be formatted, therefore we treat it as a multi line field multiLineFields.addAll(prefs.getNonWrappableFields()); } diff --git a/src/main/java/net/sf/jabref/logic/bibtex/comparator/CrossRefEntryComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/CrossRefEntryComparator.java index bc7ecb4c35b3..8b1880914487 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/comparator/CrossRefEntryComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/CrossRefEntryComparator.java @@ -18,6 +18,7 @@ import java.util.Comparator; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Compares Bibtex entries based on their 'crossref' fields. Entries including @@ -27,14 +28,11 @@ */ public class CrossRefEntryComparator implements Comparator { - private static final String CROSS_REF_FIELD = "crossref"; - - @Override public int compare(BibEntry e1, BibEntry e2) { - Boolean b1 = e1.hasField(CrossRefEntryComparator.CROSS_REF_FIELD); - Boolean b2 = e2.hasField(CrossRefEntryComparator.CROSS_REF_FIELD); + Boolean b1 = e1.hasField(FieldName.CROSSREF); + Boolean b2 = e2.hasField(FieldName.CROSSREF); if ((!b1) && (!b2)) { return 0; // secComparator.compare(e1, e2); diff --git a/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java index e4d41f28f7f2..934e0ed62567 100644 --- a/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java +++ b/src/main/java/net/sf/jabref/logic/bibtex/comparator/FieldComparator.java @@ -28,6 +28,7 @@ import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; @@ -98,9 +99,9 @@ private FieldType determineFieldType() { return FieldType.TYPE; } else if (InternalBibtexFields.getFieldExtras(this.field[0]).contains(FieldProperties.PERSON_NAMES)) { return FieldType.NAME; - } else if ("year".equals(this.field[0])) { + } else if (FieldName.YEAR.equals(this.field[0])) { return FieldType.YEAR; - } else if("month".equals(this.field[0])) { + } else if(FieldName.MONTH.equals(this.field[0])) { return FieldType.MONTH; } else { return FieldType.OTHER; diff --git a/src/main/java/net/sf/jabref/logic/bst/VM.java b/src/main/java/net/sf/jabref/logic/bst/VM.java index a5722551a461..ee4ad7303b21 100644 --- a/src/main/java/net/sf/jabref/logic/bst/VM.java +++ b/src/main/java/net/sf/jabref/logic/bst/VM.java @@ -31,6 +31,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.antlr.runtime.ANTLRFileStream; import org.antlr.runtime.ANTLRStringStream; @@ -940,8 +941,8 @@ private void read() { } for (BstEntry e : entries) { - if (!e.getFields().containsKey("crossref")) { - e.getFields().put("crossref", null); + if (!e.getFields().containsKey(FieldName.CROSSREF)) { + e.getFields().put(FieldName.CROSSREF, null); } } } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java index eccb9dbc2f2e..26bbed6ca493 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java @@ -22,6 +22,7 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryConverter; +import net.sf.jabref.model.entry.FieldName; /** * Converts the entry to BibLatex format. @@ -47,19 +48,19 @@ public List cleanup(BibEntry entry) { } // Dates: create date out of year and month, save it and delete old fields - entry.getFieldOptional("date").ifPresent(date -> { + entry.getFieldOptional(FieldName.DATE).ifPresent(date -> { if (date.isEmpty()) { - entry.getFieldOrAlias("date").ifPresent(newDate -> { - Optional oldYear = entry.getFieldOptional("year"); - Optional oldMonth = entry.getFieldOptional("month"); + entry.getFieldOrAlias(FieldName.DATE).ifPresent(newDate -> { + Optional oldYear = entry.getFieldOptional(FieldName.YEAR); + Optional oldMonth = entry.getFieldOptional(FieldName.MONTH); - entry.setField("date", newDate); - entry.clearField("year"); - entry.clearField("month"); + entry.setField(FieldName.DATE, newDate); + entry.clearField(FieldName.YEAR); + entry.clearField(FieldName.MONTH); - changes.add(new FieldChange(entry, "date", null, newDate)); - changes.add(new FieldChange(entry, "year", oldYear.orElse(null), null)); - changes.add(new FieldChange(entry, "month", oldMonth.orElse(null), null)); + changes.add(new FieldChange(entry, FieldName.DATE, null, newDate)); + changes.add(new FieldChange(entry, FieldName.YEAR, oldYear.orElse(null), null)); + changes.add(new FieldChange(entry, FieldName.MONTH, oldMonth.orElse(null), null)); }); } }); 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 c920b1b11fd2..98004464d4b4 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java @@ -22,6 +22,7 @@ import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; /** * Formats the DOI (e.g. removes http part) and also moves DOIs from note, url or ee field to the doi field. @@ -31,7 +32,7 @@ public class DoiCleanup implements CleanupJob { /** * Fields to check for DOIs. */ - private static final String[] FIELDS = {"note", "url", "ee"}; + private static final String[] FIELDS = {"note", FieldName.URL, "ee"}; @Override public List cleanup(BibEntry entry) { @@ -39,17 +40,17 @@ public List cleanup(BibEntry entry) { List changes = new ArrayList<>(); // First check if the Doi Field is empty - if (entry.hasField("doi")) { - String doiFieldValue = entry.getField("doi"); + if (entry.hasField(FieldName.DOI)) { + String doiFieldValue = entry.getField(FieldName.DOI); Optional doi = DOI.build(doiFieldValue); if (doi.isPresent()) { String newValue = doi.get().getDOI(); if (!doiFieldValue.equals(newValue)) { - entry.setField("doi", newValue); + entry.setField(FieldName.DOI, newValue); - FieldChange change = new FieldChange(entry, "doi", doiFieldValue, newValue); + FieldChange change = new FieldChange(entry, FieldName.DOI, doiFieldValue, newValue); changes.add(change); } @@ -65,12 +66,12 @@ public List cleanup(BibEntry entry) { if (doi.isPresent()) { // update Doi - String oldValue = entry.getField("doi"); + String oldValue = entry.getField(FieldName.DOI); String newValue = doi.get().getDOI(); - entry.setField("doi", newValue); + entry.setField(FieldName.DOI, newValue); - FieldChange change = new FieldChange(entry, "doi", oldValue, newValue); + FieldChange change = new FieldChange(entry, FieldName.DOI, oldValue, newValue); changes.add(change); removeFieldValue(entry, field, changes); diff --git a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java index 0de9c7440d2a..91737e907591 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java @@ -17,9 +17,9 @@ import java.util.List; import java.util.Optional; -import net.sf.jabref.Globals; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; @@ -30,7 +30,7 @@ public class FileLinksCleanup implements CleanupJob { @Override public List cleanup(BibEntry entry) { - Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + Optional oldValue = entry.getFieldOptional(FieldName.FILE); if (!oldValue.isPresent()) { return Collections.emptyList(); } @@ -40,8 +40,8 @@ public List cleanup(BibEntry entry) { // 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); + entry.setField(FieldName.FILE, newValue); + FieldChange change = new FieldChange(entry, FieldName.FILE, oldValue.get(), newValue); return Collections.singletonList(change); } return Collections.emptyList(); diff --git a/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java index c561807323c0..9600af247cf2 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java @@ -19,10 +19,10 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.Globals; import net.sf.jabref.external.ExternalFileTypes; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; @@ -42,7 +42,7 @@ 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); + String oldFileContent = entry.getField(FieldName.FILE); List fileList = new ArrayList<>(FileField.parse(oldFileContent)); int oldItemCount = fileList.size(); @@ -63,8 +63,8 @@ public List cleanup(BibEntry entry) { 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)); + entry.setField(FieldName.FILE, newValue); + changes.add(new FieldChange(entry, FieldName.FILE, oldFileContent, newValue)); } return changes; diff --git a/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java b/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java index 2b18076d37eb..3a92ad2bfd2f 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java +++ b/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java @@ -19,6 +19,7 @@ import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; public class FieldFormatterCleanups { @@ -26,7 +27,7 @@ public class FieldFormatterCleanups { private static List availableFormatters; - private boolean enabled; + private final boolean enabled; public static final FieldFormatterCleanups DEFAULT_SAVE_ACTIONS; @@ -35,8 +36,8 @@ public class FieldFormatterCleanups { availableFormatters.addAll(Formatters.ALL); List defaultFormatters = new ArrayList<>(); - defaultFormatters.add(new FieldFormatterCleanup("pages", new NormalizePagesFormatter())); - defaultFormatters.add(new FieldFormatterCleanup("month", new NormalizeMonthFormatter())); + defaultFormatters.add(new FieldFormatterCleanup(FieldName.PAGES, new NormalizePagesFormatter())); + defaultFormatters.add(new FieldFormatterCleanup(FieldName.MONTH, new NormalizeMonthFormatter())); defaultFormatters.add(new FieldFormatterCleanup("booktitle", new OrdinalsToSuperscriptFormatter())); DEFAULT_SAVE_ACTIONS = new FieldFormatterCleanups(false, defaultFormatters); } @@ -214,7 +215,7 @@ public List getAsStringList() { public static FieldFormatterCleanups parse(List formatterMetaList) { - if (formatterMetaList != null && formatterMetaList.size() >= 2) { + if ((formatterMetaList != null) && (formatterMetaList.size() >= 2)) { boolean enablementStatus = "enabled".equals(formatterMetaList.get(0)); String formatterString = formatterMetaList.get(1); return new FieldFormatterCleanups(enablementStatus, formatterString); diff --git a/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java index be761efcf0fe..6c60aa6d4bac 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java @@ -29,6 +29,7 @@ import net.sf.jabref.logic.layout.format.RemoveWhitespace; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,8 +52,8 @@ class OOCalcDatabase { public OOCalcDatabase(BibDatabase bibtex, List entries) { // Make a list of comparators for sorting the entries: List comparators = new ArrayList<>(); - comparators.add(new FieldComparator("author")); - comparators.add(new FieldComparator("year")); + comparators.add(new FieldComparator(FieldName.AUTHOR)); + comparators.add(new FieldComparator(FieldName.YEAR)); comparators.add(new FieldComparator(BibEntry.KEY_FIELD)); // Use glazed lists to get a sorted view of the entries: List entryList = new ArrayList<>(); @@ -155,25 +156,25 @@ public Document getDOMrepresentation() { for (BibEntry e : entries) { row = result.createElement("table:table-row"); addTableCell(result, row, new GetOpenOfficeType().format(e.getType())); - addTableCell(result, row, getField(e, "isbn")); + addTableCell(result, row, getField(e, FieldName.ISBN)); addTableCell(result, row, getField(e, BibEntry.KEY_FIELD)); - addTableCell(result, row, getField(e, "author"));//new AuthorLastFirst().format(getField(e, "author"))); - addTableCell(result, row, new RemoveWhitespace().format(new RemoveBrackets().format(getField(e, "title")))); - addTableCell(result, row, getField(e, "journal")); - addTableCell(result, row, getField(e, "volume")); - addTableCell(result, row, getField(e, "number")); - addTableCell(result, row, getField(e, "month")); - addTableCell(result, row, getField(e, "pages")); - addTableCell(result, row, getField(e, "year")); + addTableCell(result, row, getField(e, FieldName.AUTHOR));//new AuthorLastFirst().format(getField(e, FieldName.AUTHOR_FIELD))); + addTableCell(result, row, new RemoveWhitespace().format(new RemoveBrackets().format(getField(e, FieldName.TITLE)))); + addTableCell(result, row, getField(e, FieldName.JOURNAL)); + addTableCell(result, row, getField(e, FieldName.VOLUME)); + addTableCell(result, row, getField(e, FieldName.NUMBER)); + addTableCell(result, row, getField(e, FieldName.MONTH)); + addTableCell(result, row, getField(e, FieldName.PAGES)); + addTableCell(result, row, getField(e, FieldName.YEAR)); addTableCell(result, row, getField(e, "address")); addTableCell(result, row, getField(e, "note")); - addTableCell(result, row, getField(e, "url")); + addTableCell(result, row, getField(e, FieldName.URL)); addTableCell(result, row, getField(e, "booktitle")); addTableCell(result, row, getField(e, "chapter")); addTableCell(result, row, getField(e, "edition")); addTableCell(result, row, getField(e, "series")); - addTableCell(result, row, getField(e, "editor"));//new AuthorLastFirst().format(getField(e, "editor"))); - addTableCell(result, row, getField(e, "publisher")); + addTableCell(result, row, getField(e, FieldName.EDITOR));//new AuthorLastFirst().format(getField(e, FieldName.EDITOR_FIELD))); + addTableCell(result, row, getField(e, FieldName.PUBLISHER)); addTableCell(result, row, getField(e, "reporttype")); addTableCell(result, row, getField(e, "howpublished")); addTableCell(result, row, getField(e, "institution")); diff --git a/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java index 2cd3c68b5c28..b8dbdc2abd6b 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java @@ -29,6 +29,7 @@ import net.sf.jabref.logic.layout.format.RemoveWhitespace; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -53,8 +54,8 @@ public OpenDocumentRepresentation(BibDatabase database, List entries) this.database = database; // Make a list of comparators for sorting the entries: List comparators = new ArrayList<>(); - comparators.add(new FieldComparator("author")); - comparators.add(new FieldComparator("year")); + comparators.add(new FieldComparator(FieldName.AUTHOR)); + comparators.add(new FieldComparator(FieldName.YEAR)); comparators.add(new FieldComparator(BibEntry.KEY_FIELD)); // Use glazed lists to get a sorted view of the entries: List entryList = new ArrayList<>(); @@ -164,40 +165,40 @@ public Document getDOMrepresentation() { addTableCell(result, row, getField(e, "address")); addTableCell(result, row, getField(e, "assignee")); addTableCell(result, row, getField(e, "annote")); - addTableCell(result, row, getField(e, "author"));//new AuthorLastFirst().format(getField(e, "author"))); + addTableCell(result, row, getField(e, FieldName.AUTHOR));//new AuthorLastFirst().format(getField(e, FieldName.AUTHOR_FIELD))); addTableCell(result, row, getField(e, "booktitle")); addTableCell(result, row, getField(e, "chapter")); addTableCell(result, row, getField(e, "day")); addTableCell(result, row, getField(e, "dayfiled")); addTableCell(result, row, getField(e, "edition")); - addTableCell(result, row, getField(e, "editor"));//new AuthorLastFirst().format(getField(e, "editor"))); + addTableCell(result, row, getField(e, FieldName.EDITOR));//new AuthorLastFirst().format(getField(e, FieldName.EDITOR_FIELD))); addTableCell(result, row, getField(e, "howpublished")); addTableCell(result, row, getField(e, "institution")); - addTableCell(result, row, getField(e, "journal")); + addTableCell(result, row, getField(e, FieldName.JOURNAL)); addTableCell(result, row, getField(e, "language")); - addTableCell(result, row, getField(e, "month")); + addTableCell(result, row, getField(e, FieldName.MONTH)); addTableCell(result, row, getField(e, "monthfiled")); addTableCell(result, row, getField(e, "nationality")); addTableCell(result, row, getField(e, "note")); - addTableCell(result, row, getField(e, "number")); + addTableCell(result, row, getField(e, FieldName.NUMBER)); addTableCell(result, row, getField(e, "organization")); - addTableCell(result, row, getField(e, "pages")); - addTableCell(result, row, getField(e, "publisher")); + addTableCell(result, row, getField(e, FieldName.PAGES)); + addTableCell(result, row, getField(e, FieldName.PUBLISHER)); addTableCell(result, row, getField(e, "revision")); addTableCell(result, row, getField(e, "school")); addTableCell(result, row, getField(e, "series")); - addTableCell(result, row, new RemoveWhitespace().format(new RemoveBrackets().format(getField(e, "title")))); + addTableCell(result, row, new RemoveWhitespace().format(new RemoveBrackets().format(getField(e, FieldName.TITLE)))); addTableCell(result, row, getField(e, "reporttype")); - addTableCell(result, row, getField(e, "volume")); - addTableCell(result, row, getField(e, "year")); + addTableCell(result, row, getField(e, FieldName.VOLUME)); + addTableCell(result, row, getField(e, FieldName.YEAR)); addTableCell(result, row, getField(e, "yearfiled")); - addTableCell(result, row, getField(e, "url")); + addTableCell(result, row, getField(e, FieldName.URL)); addTableCell(result, row, ""); addTableCell(result, row, ""); addTableCell(result, row, ""); addTableCell(result, row, ""); addTableCell(result, row, ""); - addTableCell(result, row, getField(e, "isbn")); + addTableCell(result, row, getField(e, FieldName.ISBN)); table.appendChild(row); } diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ACS.java b/src/main/java/net/sf/jabref/logic/fulltext/ACS.java index 3ca52ece4a64..97c8ad144227 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ACS.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/ACS.java @@ -7,6 +7,7 @@ import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -38,7 +39,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // DOI search - Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); + Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); if(doi.isPresent()) { String source = String.format(SOURCE, doi.get().getDOI()); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java b/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java index 9011d520bedc..6532c0a3930c 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java @@ -12,6 +12,7 @@ import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; @@ -40,7 +41,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // 1. DOI - Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); + Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); // 2. Eprint Optional eprint = entry.getFieldOptional("eprint"); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java index 1f432a4985e1..d0ffe6af655f 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java @@ -24,6 +24,7 @@ import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -44,7 +45,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Objects.requireNonNull(entry); Optional pdfLink = Optional.empty(); - Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); + Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); if(doi.isPresent()) { String sciLink = doi.get().getURIAsASCIIString(); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java index 31999163cd84..cf9672676e3b 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java @@ -9,6 +9,7 @@ import net.sf.jabref.importer.fetcher.CrossRef; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -41,10 +42,10 @@ public FindFullText(List fetcher) { public Optional findFullTextPDF(BibEntry entry) { // for accuracy, fetch DOI first but do not modify entry BibEntry clonedEntry = (BibEntry) entry.clone(); - Optional doi = clonedEntry.getFieldOptional("doi"); + Optional doi = clonedEntry.getFieldOptional(FieldName.DOI); if (!doi.isPresent() || !DOI.build(doi.get()).isPresent()) { - CrossRef.findDOI(clonedEntry).ifPresent(e -> clonedEntry.setField("doi", e.getDOI())); + CrossRef.findDOI(clonedEntry).ifPresent(e -> clonedEntry.setField(FieldName.DOI, e.getDOI())); } for (FullTextFinder finder : finders) { diff --git a/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java b/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java index 4ca6152fbfec..a3a2647b2123 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java @@ -8,6 +8,7 @@ import java.util.Optional; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -30,12 +31,12 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // Search in title - if (!entry.hasField("title")) { + if (!entry.hasField(FieldName.TITLE)) { return pdfLink; } String url = String.format(SEARCH_URL, - URLEncoder.encode(entry.getFieldOptional("title").orElse(null), StandardCharsets.UTF_8.name())); + URLEncoder.encode(entry.getFieldOptional(FieldName.TITLE).orElse(null), StandardCharsets.UTF_8.name())); Document doc = Jsoup.connect(url) .userAgent("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0") // don't identify as a crawler diff --git a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java b/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java index a1fe02634523..b4262d9730a6 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java @@ -11,6 +11,7 @@ import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,7 +37,7 @@ public Optional findFullText(BibEntry entry) throws IOException { String stampString = ""; // Try URL first -- will primarily work for entries from the old IEEE search - Optional urlString = entry.getFieldOptional("url"); + Optional urlString = entry.getFieldOptional(FieldName.URL); if (urlString.isPresent()) { // Is the URL a direct link to IEEE? Matcher matcher = STAMP_PATTERN.matcher(urlString.get()); @@ -48,7 +49,7 @@ public Optional findFullText(BibEntry entry) throws IOException { // If not, try DOI if (stampString.isEmpty()) { - Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); + Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); if (doi.isPresent() && doi.get().getDOI().startsWith(IEEE_DOI) && doi.get().getURI().isPresent()) { // Download the HTML page from IEEE String resolvedDOIPage = new URLDownload(doi.get().getURI().get().toURL()) diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java b/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java index eb74da8d659a..a7036577859c 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java @@ -22,6 +22,7 @@ import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.JsonNode; @@ -52,7 +53,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // Try unique DOI first - Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); + Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); if(doi.isPresent()) { // Available in catalog? diff --git a/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java b/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java index 164b5509ea85..4136bd469fde 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java +++ b/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java @@ -22,6 +22,7 @@ import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.JsonNode; @@ -49,7 +50,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Optional pdfLink = Optional.empty(); // Try unique DOI first - Optional doi = entry.getFieldOptional("doi").flatMap(DOI::build); + Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); if(doi.isPresent()) { // Available in catalog? diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java index 0aaec654c109..81642f3a570d 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java @@ -7,6 +7,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.ISBN; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; public class ISBNChecker implements Checker { @@ -14,21 +15,21 @@ public class ISBNChecker implements Checker { @Override public List check(BibEntry entry) { - if (!entry.hasField("isbn")) { + if (!entry.hasField(FieldName.ISBN)) { return Collections.emptyList(); } // Check that the ISBN is on the correct form - ISBN isbn = new ISBN(entry.getFieldOptional("isbn").get()); + ISBN isbn = new ISBN(entry.getFieldOptional(FieldName.ISBN).get()); if (!isbn.isValidFormat()) { return Collections.singletonList( - new IntegrityMessage(Localization.lang("incorrect format"), entry, "isbn")); + new IntegrityMessage(Localization.lang("incorrect format"), entry, FieldName.ISBN)); } if (!isbn.isValidChecksum()) { return Collections - .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, "isbn")); + .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, FieldName.ISBN)); } return Collections.emptyList(); diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java index 7f075ba106a4..d08cc2f49440 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java @@ -8,6 +8,7 @@ import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; public class ISSNChecker implements Checker { @@ -16,16 +17,16 @@ public class ISSNChecker implements Checker { @Override public List check(BibEntry entry) { - if (!entry.hasField("issn")) { + if (!entry.hasField(FieldName.ISSN)) { return Collections.emptyList(); } // Check that the ISSN is on the correct form - String issn = entry.getFieldOptional("issn").get().trim(); + String issn = entry.getFieldOptional(FieldName.ISSN).get().trim(); Matcher issnMatcher = ISSN_PATTERN.matcher(issn); if (!issnMatcher.matches()) { return Collections.singletonList( - new IntegrityMessage(Localization.lang("incorrect format"), entry, "issn")); + new IntegrityMessage(Localization.lang("incorrect format"), entry, FieldName.ISSN)); } // Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Serial_Number @@ -44,7 +45,7 @@ public List check(BibEntry entry) { return Collections.emptyList(); } else { return Collections - .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, "issn")); + .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, FieldName.ISSN)); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 90f5292941bf..1a2920826f31 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -14,10 +14,10 @@ import java.util.stream.Collectors; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.Globals; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -57,12 +57,12 @@ private List checkBibtexEntry(BibEntry entry) { result.addAll(new BiblatexPagesChecker().check(entry)); } - result.addAll(new BracketChecker("title").check(entry)); + result.addAll(new BracketChecker(FieldName.TITLE).check(entry)); result.addAll(new YearChecker().check(entry)); result.addAll(new UrlChecker().check(entry)); result.addAll(new FileChecker(bibDatabaseContext).check(entry)); result.addAll(new TypeChecker().check(entry)); - result.addAll(new AbbreviationChecker("journal").check(entry)); + result.addAll(new AbbreviationChecker(FieldName.JOURNAL).check(entry)); result.addAll(new AbbreviationChecker("booktitle").check(entry)); result.addAll(new BibStringChecker().check(entry)); result.addAll(new HTMLCharacterChecker().check(entry)); @@ -83,13 +83,13 @@ private static class TypeChecker implements Checker { @Override public List check(BibEntry entry) { - Optional value = entry.getFieldOptional("pages"); + Optional value = entry.getFieldOptional(FieldName.PAGES); if (!value.isPresent()) { return Collections.emptyList(); } if ("proceedings".equalsIgnoreCase(entry.getType())) { - return Collections.singletonList(new IntegrityMessage(Localization.lang("wrong entry type as proceedings has page numbers"), entry, "pages")); + return Collections.singletonList(new IntegrityMessage(Localization.lang("wrong entry type as proceedings has page numbers"), entry, FieldName.PAGES)); } return Collections.emptyList(); @@ -147,7 +147,7 @@ private FileChecker(BibDatabaseContext context) { @Override public List check(BibEntry entry) { - Optional value = entry.getFieldOptional(Globals.FILE_FIELD); + Optional value = entry.getFieldOptional(FieldName.FILE); if (!value.isPresent()) { return Collections.emptyList(); } @@ -161,7 +161,7 @@ public List check(BibEntry entry) { if ((!file.isPresent()) || !file.get().exists()) { return Collections.singletonList( new IntegrityMessage(Localization.lang("link should refer to a correct file path"), entry, - Globals.FILE_FIELD)); + FieldName.FILE)); } } @@ -173,13 +173,13 @@ private static class UrlChecker implements Checker { @Override public List check(BibEntry entry) { - Optional value = entry.getFieldOptional("url"); + Optional value = entry.getFieldOptional(FieldName.URL); if (!value.isPresent()) { return Collections.emptyList(); } if (!value.get().contains("://")) { - return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a protocol") + ": http[s]://, file://, ftp://, ...", entry, "url")); + return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a protocol") + ": http[s]://, file://, ftp://, ...", entry, FieldName.URL)); } return Collections.emptyList(); @@ -255,7 +255,7 @@ private static class TitleChecker implements Checker { @Override public List check(BibEntry entry) { - Optional value = entry.getFieldOptional("title"); + Optional value = entry.getFieldOptional(FieldName.TITLE); if (!value.isPresent()) { return Collections.emptyList(); } @@ -282,7 +282,7 @@ public List check(BibEntry entry) { boolean hasCapitalLettersThatBibtexWillConvertToSmallerOnes = HAS_CAPITAL_LETTERS.test(valueOnlySpacesWithinCurlyBraces); if (hasCapitalLettersThatBibtexWillConvertToSmallerOnes) { - return Collections.singletonList(new IntegrityMessage(Localization.lang("large capitals are not masked using curly brackets {}"), entry, "title")); + return Collections.singletonList(new IntegrityMessage(Localization.lang("large capitals are not masked using curly brackets {}"), entry, FieldName.TITLE)); } return Collections.emptyList(); @@ -298,13 +298,13 @@ private static class YearChecker implements Checker { */ @Override public List check(BibEntry entry) { - Optional value = entry.getFieldOptional("year"); + Optional value = entry.getFieldOptional(FieldName.YEAR); if (!value.isPresent()) { return Collections.emptyList(); } if (!CONTAINS_FOUR_DIGIT.test(value.get().trim())) { - return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a four digit number"), entry, "year")); + return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a four digit number"), entry, FieldName.YEAR)); } return Collections.emptyList(); @@ -339,13 +339,13 @@ private static class PagesChecker implements Checker { */ @Override public List check(BibEntry entry) { - Optional value = entry.getFieldOptional("pages"); + Optional value = entry.getFieldOptional(FieldName.PAGES); if (!value.isPresent()) { return Collections.emptyList(); } if (!VALID_PAGE_NUMBER.test(value.get().trim())) { - return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a valid page number range"), entry, "pages")); + return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a valid page number range"), entry, FieldName.PAGES)); } return Collections.emptyList(); @@ -376,13 +376,13 @@ private static class BiblatexPagesChecker implements Checker { */ @Override public List check(BibEntry entry) { - Optional value = entry.getFieldOptional("pages"); + Optional value = entry.getFieldOptional(FieldName.PAGES); if (!value.isPresent()) { return Collections.emptyList(); } if (!VALID_PAGE_NUMBER.test(value.get().trim())) { - return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a valid page number range"), entry, "pages")); + return Collections.singletonList(new IntegrityMessage(Localization.lang("should contain a valid page number range"), entry, FieldName.PAGES)); } return Collections.emptyList(); @@ -404,7 +404,7 @@ public List check(BibEntry entry) { Map fields = entry.getFieldMap(); // the url field should not be checked for hashes, as they are legal in this field - fields.remove("url"); + fields.remove(FieldName.URL); for (Map.Entry field : fields.entrySet()) { Matcher hashMatcher = UNESCAPED_HASH.matcher(field.getValue()); diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index c36447041889..88467cb77f43 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -33,6 +33,7 @@ import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -602,7 +603,7 @@ public static String makeLabel(BibEntry entry, String value) { * form "pureauth..." which does not do this fallback * substitution of editor. */ - String authString = entry.getField("author"); + String authString = entry.getField(FieldName.AUTHOR); if (authString != null) { authString = normalize(database.resolveForStrings(authString)); } @@ -614,7 +615,7 @@ public static String makeLabel(BibEntry entry, String value) { } if ((authString == null) || authString.isEmpty()) { - authString = entry.getField("editor"); + authString = entry.getField(FieldName.EDITOR); if (authString == null) { authString = ""; } else { @@ -688,39 +689,39 @@ else if ("authorLast".equals(val)) { // Gather all markers starting with "ed" here, so we // don't have to check all the time. if ("edtr".equals(val)) { - return firstAuthor(entry.getField("editor")); + return firstAuthor(entry.getField(FieldName.EDITOR)); } else if ("edtrForeIni".equals(val)) { - return firstAuthorForenameInitials(entry.getField("editor")); + return firstAuthorForenameInitials(entry.getField(FieldName.EDITOR)); } else if ("editors".equals(val)) { - return allAuthors(entry.getField("editor")); + return allAuthors(entry.getField(FieldName.EDITOR)); // Last author's last name } else if ("editorLast".equals(val)) { - return lastAuthor(entry.getField("editor")); + return lastAuthor(entry.getField(FieldName.EDITOR)); } else if ("editorLastForeIni".equals(val)) { - return lastAuthorForenameInitials(entry.getField("editor")); + return lastAuthorForenameInitials(entry.getField(FieldName.EDITOR)); } else if ("editorIni".equals(val)) { - return oneAuthorPlusIni(entry.getField("editor")); + return oneAuthorPlusIni(entry.getField(FieldName.EDITOR)); } else if (val.matches("edtrIni[\\d]+")) { int num = Integer.parseInt(val.substring(7)); - String s = authIniN(entry.getField("editor"), num); + String s = authIniN(entry.getField(FieldName.EDITOR), num); return s == null ? "" : s; } else if (val.matches("edtr[\\d]+_[\\d]+")) { String[] nums = val.substring(4).split("_"); - String s = authNofMth(entry.getField("editor"), + String s = authNofMth(entry.getField(FieldName.EDITOR), Integer.parseInt(nums[0]), Integer.parseInt(nums[1]) - 1); return s == null ? "" : s; } else if ("edtr.edtr.ea".equals(val)) { - String s = authAuthEa(entry.getField("editor")); + String s = authAuthEa(entry.getField(FieldName.EDITOR)); return s == null ? "" : s; } else if ("edtrshort".equals(val)) { - String s = authshort(entry.getField("editor")); + String s = authshort(entry.getField(FieldName.EDITOR)); return s == null ? "" : s; } // authN. First N chars of the first author's last // name. else if (val.matches("edtr\\d+")) { - String fa = firstAuthor(entry.getField("editor")); + String fa = firstAuthor(entry.getField(FieldName.EDITOR)); if (fa == null) { return ""; } @@ -735,17 +736,17 @@ else if (val.matches("edtr\\d+")) { return getField(entry, val); } } else if ("firstpage".equals(val)) { - return firstPage(entry.getField("pages")); + return firstPage(entry.getField(FieldName.PAGES)); } else if ("lastpage".equals(val)) { - return lastPage(entry.getField("pages")); + return lastPage(entry.getField(FieldName.PAGES)); } else if ("shorttitle".equals(val)) { - return getTitleWords(3, entry.getField("title")); + return getTitleWords(3, entry.getField(FieldName.TITLE)); } else if ("shorttitleINI".equals(val)) { - return keepLettersAndDigitsOnly(applyModifiers(getTitleWordsWithSpaces(3, entry.getField("title")), new String[] {"abbr"}, 0)); + return keepLettersAndDigitsOnly(applyModifiers(getTitleWordsWithSpaces(3, entry.getField(FieldName.TITLE)), new String[] {"abbr"}, 0)); } else if ("veryshorttitle".equals(val)) { - return getTitleWords(1, entry.getField("title")); + return getTitleWords(1, entry.getField(FieldName.TITLE)); } else if ("shortyear".equals(val)) { - String ss = entry.getFieldOrAlias("year").orElse(""); + String ss = entry.getFieldOrAlias(FieldName.YEAR).orElse(""); if (ss.isEmpty()) { return ss; } else if (ss.startsWith("in") || ss.startsWith("sub")) { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookAuthors.java b/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookAuthors.java index 345a99eda7a6..d9ed690eabb1 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookAuthors.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookAuthors.java @@ -39,6 +39,7 @@ import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; +import net.sf.jabref.model.entry.FieldName; /** * Create DocBook authors formatter. @@ -55,7 +56,7 @@ public String format(String fieldText) { AuthorList al = AuthorList.parse(fieldText); - addBody(sb, al, "author"); + addBody(sb, al, FieldName.AUTHOR); return sb.toString(); } diff --git a/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookEditors.java b/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookEditors.java index af7f466eda5d..396808bf3cfe 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookEditors.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/CreateDocBookEditors.java @@ -37,6 +37,7 @@ package net.sf.jabref.logic.layout.format; import net.sf.jabref.model.entry.AuthorList; +import net.sf.jabref.model.entry.FieldName; /** * Create DocBook editors formatter. @@ -48,7 +49,7 @@ public String format(String fieldText) { // L.Xue StringBuilder sb = new StringBuilder(100); AuthorList al = AuthorList.parse(fieldText); - addBody(sb, al, "editor"); + addBody(sb, al, FieldName.EDITOR); return sb.toString(); } diff --git a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java index dc9b55a108cb..3c161db06529 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java @@ -24,6 +24,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.ParamLayoutFormatter; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; import net.sf.jabref.preferences.JabRefPreferences; @@ -82,7 +83,7 @@ public String format(String field) { // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: if (prefs.fileDirForDatabase == null) { - dirs = Collections.singletonList(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); + dirs = Collections.singletonList(prefs.get(FieldName.FILE + Globals.DIR_SUFFIX)); } else { dirs = prefs.fileDirForDatabase; } diff --git a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java index 9920e60a55a6..592ca3b4ec56 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java @@ -27,6 +27,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.AbstractParamLayoutFormatter; import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; import net.sf.jabref.preferences.JabRefPreferences; @@ -178,7 +179,7 @@ public String format(String field) { // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: if (prefs.fileDirForDatabase == null) { - dirs = Collections.singletonList(prefs.get(Globals.FILE_FIELD + Globals.DIR_SUFFIX)); + dirs = Collections.singletonList(prefs.get(FieldName.FILE + Globals.DIR_SUFFIX)); } else { dirs = prefs.fileDirForDatabase; } diff --git a/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java b/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java index ec10cbd7d861..abf9d73c0b97 100644 --- a/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java +++ b/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java @@ -35,6 +35,7 @@ import net.sf.jabref.logic.layout.format.XMLChars; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -87,27 +88,27 @@ private MODSEntry() { public MODSEntry(BibEntry bibtex) { this(); - handledExtensions.add(MODSEntry.BIBTEX + "publisher"); - handledExtensions.add(MODSEntry.BIBTEX + "title"); + handledExtensions.add(MODSEntry.BIBTEX + FieldName.PUBLISHER); + handledExtensions.add(MODSEntry.BIBTEX + FieldName.TITLE); handledExtensions.add(MODSEntry.BIBTEX + BibEntry.KEY_FIELD); handledExtensions.add(MODSEntry.BIBTEX + "author"); populateFromBibtex(bibtex); } private void populateFromBibtex(BibEntry bibtex) { - if (bibtex.hasField("title")) { + if (bibtex.hasField(FieldName.TITLE)) { if (CHARFORMAT) { - title = chars.format(bibtex.getField("title")); + title = chars.format(bibtex.getField(FieldName.TITLE)); } else { - title = bibtex.getField("title"); + title = bibtex.getField(FieldName.TITLE); } } - if (bibtex.hasField("publisher")) { + if (bibtex.hasField(FieldName.PUBLISHER)) { if (CHARFORMAT) { - publisher = chars.format(bibtex.getField("publisher")); + publisher = chars.format(bibtex.getField(FieldName.PUBLISHER)); } else { - publisher = bibtex.getField("publisher"); + publisher = bibtex.getField(FieldName.PUBLISHER); } } @@ -124,21 +125,21 @@ private void populateFromBibtex(BibEntry bibtex) { date = getDate(bibtex); genre = getMODSgenre(bibtex); - if (bibtex.hasField("author")) { - authors = getAuthors(bibtex.getField("author")); + if (bibtex.hasField(FieldName.AUTHOR)) { + authors = getAuthors(bibtex.getField(FieldName.AUTHOR)); } if ("article".equals(bibtex.getType()) || "inproceedings".equals(bibtex.getType())) { host = new MODSEntry(); host.entryType = "relatedItem"; host.title = bibtex.getField("booktitle"); - host.publisher = bibtex.getField("publisher"); - host.number = bibtex.getField("number"); - if (bibtex.hasField("volume")) { - host.volume = bibtex.getField("volume"); + host.publisher = bibtex.getField(FieldName.PUBLISHER); + host.number = bibtex.getField(FieldName.NUMBER); + if (bibtex.hasField(FieldName.VOLUME)) { + host.volume = bibtex.getField(FieldName.VOLUME); } host.issuance = "continuing"; - if (bibtex.hasField("pages")) { - host.pages = new PageNumbers(bibtex.getField("pages")); + if (bibtex.hasField(FieldName.PAGES)) { + host.pages = new PageNumbers(bibtex.getField(FieldName.PAGES)); } } @@ -179,8 +180,8 @@ private List getAuthors(String authors) { /* construct a MODS date object */ private static String getDate(BibEntry bibtex) { StringBuilder result = new StringBuilder(); - bibtex.getFieldOptional("year").ifPresent(result::append); - bibtex.getFieldOptional("month").ifPresent(result.append('-')::append); + bibtex.getFieldOptional(FieldName.YEAR).ifPresent(result::append); + bibtex.getFieldOptional(FieldName.MONTH).ifPresent(result.append('-')::append); return result.toString(); } @@ -249,7 +250,7 @@ public Element getDOMrepresentation(Document d) { Element originInfo = d.createElement("originInfo"); mods.appendChild(originInfo); if (this.publisher != null) { - Element publisher = d.createElement("publisher"); + Element publisher = d.createElement(FieldName.PUBLISHER); publisher.appendChild(d.createTextNode(StringUtil.stripNonValidXMLCharacters(this.publisher))); originInfo.appendChild(publisher); } diff --git a/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java b/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java index 7965ac433752..acd7292073f8 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java +++ b/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java @@ -10,6 +10,7 @@ import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.logic.mods.PersonName; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; public class BibTeXConverter { private static final String MSBIB_PREFIX = "msbib-"; @@ -31,7 +32,7 @@ public static BibEntry convert(MSBibEntry entry) { String msField = field.getKey(); String value = field.getValue(); - if (value != null && MSBibMapping.getBibTeXField(msField) != null) { + if ((value != null) && (MSBibMapping.getBibTeXField(msField) != null)) { fieldValues.put(MSBibMapping.getBibTeXField(msField), value); } } @@ -42,9 +43,9 @@ public static BibEntry convert(MSBibEntry entry) { fieldValues.put("language", MSBibMapping.getLanguage(lcid)); } - addAuthor(fieldValues, "author", entry.authors); + addAuthor(fieldValues, FieldName.AUTHOR, entry.authors); addAuthor(fieldValues, MSBIB_PREFIX + "bookauthor", entry.bookAuthors); - addAuthor(fieldValues, "editor", entry.editors); + addAuthor(fieldValues, FieldName.EDITOR, entry.editors); addAuthor(fieldValues, MSBIB_PREFIX + "translator", entry.translators); addAuthor(fieldValues, MSBIB_PREFIX + "producername", entry.producerNames); addAuthor(fieldValues, MSBIB_PREFIX + "composer", entry.composers); @@ -59,7 +60,7 @@ public static BibEntry convert(MSBibEntry entry) { addAuthor(fieldValues, MSBIB_PREFIX + "counsel", entry.counsels); if (entry.pages != null) { - fieldValues.put("pages", entry.pages.toString("--")); + fieldValues.put(FieldName.PAGES, entry.pages.toString("--")); } parseStandardNumber(entry.standardNumber, fieldValues); @@ -103,10 +104,10 @@ private static void parseStandardNumber(String standardNum, Map if (standardNum == null) { return; } - parseSingleStandardNumber("ISBN", "isbn", standardNum, map); - parseSingleStandardNumber("ISSN", "issn", standardNum, map); + parseSingleStandardNumber("ISBN", FieldName.ISBN, standardNum, map); + parseSingleStandardNumber("ISSN", FieldName.ISSN, standardNum, map); parseSingleStandardNumber("LCCN", "lccn", standardNum, map); parseSingleStandardNumber("MRN", "mrnumber", standardNum, map); - parseSingleStandardNumber("DOI", "doi", standardNum, map); + parseSingleStandardNumber("DOI", FieldName.DOI, standardNum, map); } } diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java index 9579d748debe..95506884b93c 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java @@ -8,6 +8,7 @@ import net.sf.jabref.logic.mods.PageNumbers; import net.sf.jabref.logic.mods.PersonName; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; public class MSBibConverter { private static final String MSBIB_PREFIX = "msbib-"; @@ -35,8 +36,8 @@ public static MSBibEntry convert(BibEntry entry) { result.conferenceName = entry.getField("booktitle"); } - if (entry.hasField("pages")) { - result.pages = new PageNumbers(entry.getField("pages")); + if (entry.hasField(FieldName.PAGES)) { + result.pages = new PageNumbers(entry.getField(FieldName.PAGES)); } if (entry.hasField(MSBIB_PREFIX + "accessed")) { @@ -44,13 +45,13 @@ public static MSBibEntry convert(BibEntry entry) { } // TODO: currently this can never happen - if ("SoundRecording".equals(msbibType) && (entry.hasField("title"))) { - result.albumTitle = entry.getField("title"); + if ("SoundRecording".equals(msbibType) && (entry.hasField(FieldName.TITLE))) { + result.albumTitle = entry.getField(FieldName.TITLE); } // TODO: currently this can never happen - if ("Interview".equals(msbibType) && (entry.hasField("title"))) { - result.broadcastTitle = entry.getField("title"); + if ("Interview".equals(msbibType) && (entry.hasField(FieldName.TITLE))) { + result.broadcastTitle = entry.getField(FieldName.TITLE); } // Value must be converted @@ -59,11 +60,11 @@ public static MSBibEntry convert(BibEntry entry) { } result.standardNumber = ""; - if (entry.hasField("isbn")) { - result.standardNumber += " ISBN: " + entry.getField("isbn"); + if (entry.hasField(FieldName.ISBN)) { + result.standardNumber += " ISBN: " + entry.getField(FieldName.ISBN); } - if (entry.hasField("issn")) { - result.standardNumber += " ISSN: " + entry.getField("issn"); + if (entry.hasField(FieldName.ISSN)) { + result.standardNumber += " ISSN: " + entry.getField(FieldName.ISSN); } if (entry.hasField("lccn")) { result.standardNumber += " LCCN: " + entry.getField("lccn"); @@ -71,8 +72,8 @@ public static MSBibEntry convert(BibEntry entry) { if (entry.hasField("mrnumber")) { result.standardNumber += " MRN: " + entry.getField("mrnumber"); } - if (entry.hasField("doi")) { - result.standardNumber += " DOI: " + entry.getField("doi"); + if (entry.hasField(FieldName.DOI)) { + result.standardNumber += " DOI: " + entry.getField(FieldName.DOI); } if (result.standardNumber.isEmpty()) { result.standardNumber = null; @@ -98,21 +99,21 @@ public static MSBibEntry convert(BibEntry entry) { // TODO: currently this can never happen if (("InternetSite".equals(msbibType) || "DocumentFromInternetSite".equals(msbibType)) - && (entry.hasField("title"))) { - result.internetSiteTitle = entry.getField("title"); + && (entry.hasField(FieldName.TITLE))) { + result.internetSiteTitle = entry.getField(FieldName.TITLE); } // TODO: currently only Misc can happen if (("ElectronicSource".equals(msbibType) || "Art".equals(msbibType) || "Misc".equals(msbibType)) - && (entry.hasField("title"))) { - result.publicationTitle = entry.getField("title"); + && (entry.hasField(FieldName.TITLE))) { + result.publicationTitle = entry.getField(FieldName.TITLE); } - if (entry.hasField("author")) { - result.authors = getAuthors(entry.getField("author")); + if (entry.hasField(FieldName.AUTHOR)) { + result.authors = getAuthors(entry.getField(FieldName.AUTHOR)); } - if (entry.hasField("editor")) { - result.editors = getAuthors(entry.getField("editor")); + if (entry.hasField(FieldName.EDITOR)) { + result.editors = getAuthors(entry.getField(FieldName.EDITOR)); } return result; diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java index 3b6b63e69469..89a78d357783 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java @@ -5,6 +5,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexEntryTypes; +import net.sf.jabref.model.entry.FieldName; import com.google.common.collect.HashBiMap; @@ -16,29 +17,29 @@ public class MSBibMapping { static { bibtexToMSBib.put(BibEntry.KEY_FIELD, "Tag"); - bibtexToMSBib.put("title", "Title"); - bibtexToMSBib.put("year", "Year"); - bibtexToMSBib.put("month", "Month"); + bibtexToMSBib.put(FieldName.TITLE, "Title"); + bibtexToMSBib.put(FieldName.YEAR, "Year"); + bibtexToMSBib.put(FieldName.MONTH, "Month"); bibtexToMSBib.put("note", "Comments"); - bibtexToMSBib.put("volume", "Volume"); + bibtexToMSBib.put(FieldName.VOLUME, "Volume"); bibtexToMSBib.put("language", "LCID"); bibtexToMSBib.put("edition", "Edition"); - bibtexToMSBib.put("publisher", "Publisher"); + bibtexToMSBib.put(FieldName.PUBLISHER, "Publisher"); bibtexToMSBib.put("booktitle", "BookTitle"); //bibtexToMSBib.put("booktitle", "ConferenceName"); - //bibtexToMSBib.put("pages", "Pages"); + //bibtexToMSBib.put(FieldName.PAGES, "Pages"); bibtexToMSBib.put("chapter", "ChapterNumber"); - bibtexToMSBib.put("journal", "JournalName"); - bibtexToMSBib.put("number", "Issue"); + bibtexToMSBib.put(FieldName.JOURNAL, "JournalName"); + bibtexToMSBib.put(FieldName.NUMBER, "Issue"); bibtexToMSBib.put("school", "Department"); bibtexToMSBib.put("institution", "Institution"); - bibtexToMSBib.put("doi", "DOI"); - bibtexToMSBib.put("url", "URL"); + bibtexToMSBib.put(FieldName.DOI, "DOI"); + bibtexToMSBib.put(FieldName.URL, "URL"); // BibTeX/Biblatex only fields bibtexToMSBib.put("series", BIBTEX_PREFIX + "Series"); - bibtexToMSBib.put("abstract", BIBTEX_PREFIX + "Abstract"); - bibtexToMSBib.put("keywords", BIBTEX_PREFIX + "KeyWords"); - bibtexToMSBib.put("crossref", BIBTEX_PREFIX + "CrossRef"); + bibtexToMSBib.put(FieldName.ABSTRACT, BIBTEX_PREFIX + "Abstract"); + bibtexToMSBib.put(FieldName.KEYWORDS, BIBTEX_PREFIX + "KeyWords"); + bibtexToMSBib.put(FieldName.CROSSREF, BIBTEX_PREFIX + "CrossRef"); bibtexToMSBib.put("howpublished", BIBTEX_PREFIX + "HowPublished"); bibtexToMSBib.put("affiliation", BIBTEX_PREFIX + "Affiliation"); bibtexToMSBib.put("contents", BIBTEX_PREFIX + "Contents"); diff --git a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java index ff6a1255e3f7..488d1412042c 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java @@ -45,6 +45,7 @@ import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; @@ -189,7 +190,7 @@ private void setDefaultProperties() { // Set default properties for the citation marker: citProperties.put(AUTHOR_FIELD, "author/editor"); - citProperties.put(YEAR_FIELD, "year"); + citProperties.put(YEAR_FIELD, FieldName.YEAR); citProperties.put(MAX_AUTHORS, 3); citProperties.put(MAX_AUTHORS_FIRST, -1); citProperties.put(AUTHOR_SEPARATOR, ", "); 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 3bbc88c267d3..550ef8e8f302 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 @@ -37,13 +37,13 @@ import java.util.regex.Pattern; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.Globals; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; import net.sf.jabref.preferences.JabRefPreferences; @@ -373,7 +373,7 @@ public static List getListOfLinkedFiles(List bes, List f List result = new ArrayList<>(); for (BibEntry entry : bes) { - entry.getFieldOptional(Globals.FILE_FIELD).ifPresent(fileField -> { + entry.getFieldOptional(FieldName.FILE).ifPresent(fileField -> { List fileList = FileField.parse(fileField); for (ParsedFileField file : fileList) { expandFilename(file.getLink(), fileDirs).ifPresent(result::add); diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java index 0269a6706294..e5bb44522eb6 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java @@ -28,6 +28,7 @@ import net.sf.jabref.model.entry.Author; import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -53,9 +54,9 @@ public class XMPSchemaBibtex extends XMPSchema { static { - XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add("abstract"); + XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add(FieldName.ABSTRACT); XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add("note"); - XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add("review"); + XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add(FieldName.REVIEW); } /** diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index d4280c0cfb2c..c50e16f526b4 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -54,6 +54,7 @@ import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.MonthUtil; import net.sf.jabref.preferences.JabRefPreferences; @@ -262,22 +263,22 @@ public static Optional getBibtexEntryFromDocumentInformation( String s = di.getAuthor(); if (s != null) { - entry.setField("author", s); + entry.setField(FieldName.AUTHOR, s); } s = di.getTitle(); if (s != null) { - entry.setField("title", s); + entry.setField(FieldName.TITLE, s); } s = di.getKeywords(); if (s != null) { - entry.setField("keywords", s); + entry.setField(FieldName.KEYWORDS, s); } s = di.getSubject(); if (s != null) { - entry.setField("abstract", s); + entry.setField(FieldName.ABSTRACT, s); } COSDictionary dict = di.getDictionary(); @@ -323,7 +324,7 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor */ List contributors = dcSchema.getContributors(); if ((contributors != null) && !contributors.isEmpty()) { - entry.setField("editor", String.join(" and ", contributors)); + entry.setField(FieldName.EDITOR, String.join(" and ", contributors)); } /** @@ -331,7 +332,7 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor */ List creators = dcSchema.getCreators(); if ((creators != null) && !creators.isEmpty()) { - entry.setField("author", String.join(" and ", creators)); + entry.setField(FieldName.AUTHOR, String.join(" and ", creators)); } /** @@ -347,9 +348,9 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor // Ignored } if (c != null) { - entry.setField("year", String.valueOf(c.get(Calendar.YEAR))); + entry.setField(FieldName.YEAR, String.valueOf(c.get(Calendar.YEAR))); if (date.length() > 4) { - entry.setField("month", MonthUtil.getMonthByIndex(c.get(Calendar.MONTH)).bibtexFormat); + entry.setField(FieldName.MONTH, MonthUtil.getMonthByIndex(c.get(Calendar.MONTH)).bibtexFormat); } } } @@ -359,7 +360,7 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor */ String s = dcSchema.getDescription(); if (s != null) { - entry.setField("abstract", s); + entry.setField(FieldName.ABSTRACT, s); } /** @@ -367,7 +368,7 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor */ s = dcSchema.getIdentifier(); if (s != null) { - entry.setField("doi", s); + entry.setField(FieldName.DOI, s); } /** @@ -426,7 +427,7 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor */ s = dcSchema.getTitle(); if (s != null) { - entry.setField("title", s); + entry.setField(FieldName.TITLE, s); } /** @@ -618,7 +619,7 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, continue; } - if ("editor".equals(field)) { + if (FieldName.EDITOR.equals(field)) { String authors = resolvedEntry.getField(field); /** @@ -676,12 +677,12 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, continue; } - if ("month".equals(field)) { + if (FieldName.MONTH.equals(field)) { // Dealt with in year continue; } - if ("year".equals(field)) { + if (FieldName.YEAR.equals(field)) { /** * Year + Month -> Date @@ -715,7 +716,7 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, * * Bibtex-Fields used: abstract */ - if ("abstract".equals(field)) { + if (FieldName.ABSTRACT.equals(field)) { String o = resolvedEntry.getField(field); dcSchema.setDescription(o); continue; @@ -734,7 +735,7 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, * * Bibtex-Fields used: doi */ - if ("doi".equals(field)) { + if (FieldName.DOI.equals(field)) { String o = resolvedEntry.getField(field); dcSchema.setIdentifier(o); continue; @@ -762,7 +763,7 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, * * Bibtex-Fields used: doi */ - if ("publisher".equals(field)) { + if (FieldName.PUBLISHER.equals(field)) { String o = entry.getField(field); dcSchema.addPublisher(o); continue; @@ -800,7 +801,7 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, * * Bibtex-Fields used: doi */ - if ("keywords".equals(field)) { + if (FieldName.KEYWORDS.equals(field)) { String o = entry.getField(field); String[] keywords = o.split(","); for (String keyword : keywords) { @@ -824,7 +825,7 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, * * Bibtex-Fields used: title */ - if ("title".equals(field)) { + if (FieldName.TITLE.equals(field)) { String o = entry.getField(field); dcSchema.setTitle(o); continue; @@ -1010,11 +1011,11 @@ private static void writeDocumentInformation(PDDocument document, // erase field instead of adding it if ("author".equals(field)) { di.setAuthor(null); - } else if ("title".equals(field)) { + } else if (FieldName.TITLE.equals(field)) { di.setTitle(null); - } else if ("keywords".equals(field)) { + } else if (FieldName.KEYWORDS.equals(field)) { di.setKeywords(null); - } else if ("abstract".equals(field)) { + } else if (FieldName.ABSTRACT.equals(field)) { di.setSubject(null); } else { di.setCustomMetadataValue("bibtex/" + field, null); @@ -1023,13 +1024,13 @@ private static void writeDocumentInformation(PDDocument document, } if ("author".equals(field)) { - di.setAuthor(resolvedEntry.getField("author")); - } else if ("title".equals(field)) { - di.setTitle(resolvedEntry.getField("title")); - } else if ("keywords".equals(field)) { - di.setKeywords(resolvedEntry.getField("keywords")); - } else if ("abstract".equals(field)) { - di.setSubject(resolvedEntry.getField("abstract")); + di.setAuthor(resolvedEntry.getField(FieldName.AUTHOR)); + } else if (FieldName.TITLE.equals(field)) { + di.setTitle(resolvedEntry.getField(FieldName.TITLE)); + } else if (FieldName.KEYWORDS.equals(field)) { + di.setKeywords(resolvedEntry.getField(FieldName.KEYWORDS)); + } else if (FieldName.ABSTRACT.equals(field)) { + di.setSubject(resolvedEntry.getField(FieldName.ABSTRACT)); } else { di.setCustomMetadataValue("bibtex/" + field, resolvedEntry.getField(field)); } diff --git a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java index fb17366a9603..857b34e934d4 100644 --- a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java +++ b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java @@ -38,6 +38,7 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; @@ -77,7 +78,7 @@ public boolean isActionNecessary(ParserResult pr) { // Only offer to upgrade links if the pdf/ps fields are used: offerChangeDatabase = linksFound(pr.getDatabase(), FileLinksUpgradeWarning.FIELDS_TO_LOOK_FOR); // If the "file" directory is not set, offer to migrate pdf/ps dir: - offerSetFileDir = !Globals.prefs.hasKey(Globals.FILE_FIELD + Globals.DIR_SUFFIX) + offerSetFileDir = !Globals.prefs.hasKey(FieldName.FILE + Globals.DIR_SUFFIX) && (Globals.prefs.hasKey("pdfDirectory") || Globals.prefs.hasKey("psDirectory")); // First check if this warning is disabled: @@ -199,7 +200,7 @@ private void makeChanges(BasePanel panel, ParserResult pr, boolean upgradePrefs, } if (fileDir != null) { - Globals.prefs.put(Globals.FILE_FIELD + Globals.DIR_SUFFIX, fileDir); + Globals.prefs.put(FieldName.FILE + Globals.DIR_SUFFIX, fileDir); } if (upgradePrefs) { @@ -214,7 +215,7 @@ private void makeChanges(BasePanel panel, ParserResult pr, boolean upgradePrefs, if (!gfs.isEmpty()) { sb.append(';'); } - sb.append(Globals.FILE_FIELD); + sb.append(FieldName.FILE); Globals.prefs.put(JabRefPreferences.CUSTOM_TAB_FIELDS + "0", sb.toString()); Globals.prefs.updateEntryEditorTabList(); panel.frame().removeCachedEntryEditors(); @@ -229,7 +230,7 @@ private boolean showsFileInGenFields() { outer: for (int i = 0; i < tabList.getTabCount(); i++) { List fields = tabList.getTabFields(i); for (String field : fields) { - if (field.equals(Globals.FILE_FIELD)) { + if (field.equals(FieldName.FILE)) { found = true; break outer; } diff --git a/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java b/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java index 01e7d669a0ca..2d684ac8e836 100644 --- a/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java @@ -4,6 +4,7 @@ import java.util.Map; import net.sf.jabref.Globals; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; public class PreferencesMigrations { @@ -17,10 +18,10 @@ public static void replaceAbstractField() { // Jabref 1.55 moves the abstract to its own tab. String genFields = Globals.prefs.get(JabRefPreferences.GENERAL_FIELDS); - if (genFields.contains("abstract")) { + if (genFields.contains(FieldName.ABSTRACT)) { String newGen; - if ("abstract".equals(genFields)) { + if (FieldName.ABSTRACT.equals(genFields)) { newGen = ""; } else if (genFields.contains(";abstract;")) { newGen = genFields.replace(";abstract;", ";"); @@ -86,18 +87,18 @@ public static void upgradeSortOrder() { if (prefs.get(JabRefPreferences.EXPORT_IN_SPECIFIED_ORDER, null) == null) { if (prefs.getBoolean("exportInStandardOrder", false)) { prefs.putBoolean(JabRefPreferences.EXPORT_IN_SPECIFIED_ORDER, true); - prefs.put(JabRefPreferences.EXPORT_PRIMARY_SORT_FIELD, "author"); - prefs.put(JabRefPreferences.EXPORT_SECONDARY_SORT_FIELD, "editor"); - prefs.put(JabRefPreferences.EXPORT_TERTIARY_SORT_FIELD, "year"); + prefs.put(JabRefPreferences.EXPORT_PRIMARY_SORT_FIELD, FieldName.AUTHOR); + prefs.put(JabRefPreferences.EXPORT_SECONDARY_SORT_FIELD, FieldName.EDITOR); + prefs.put(JabRefPreferences.EXPORT_TERTIARY_SORT_FIELD, FieldName.YEAR); prefs.putBoolean(JabRefPreferences.EXPORT_PRIMARY_SORT_DESCENDING, false); prefs.putBoolean(JabRefPreferences.EXPORT_SECONDARY_SORT_DESCENDING, false); prefs.putBoolean(JabRefPreferences.EXPORT_TERTIARY_SORT_DESCENDING, false); } else if (prefs.getBoolean("exportInTitleOrder", false)) { // exportInTitleOrder => title, author, editor prefs.putBoolean(JabRefPreferences.EXPORT_IN_SPECIFIED_ORDER, true); - prefs.put(JabRefPreferences.EXPORT_PRIMARY_SORT_FIELD, "title"); - prefs.put(JabRefPreferences.EXPORT_SECONDARY_SORT_FIELD, "author"); - prefs.put(JabRefPreferences.EXPORT_TERTIARY_SORT_FIELD, "editor"); + prefs.put(JabRefPreferences.EXPORT_PRIMARY_SORT_FIELD, FieldName.TITLE); + prefs.put(JabRefPreferences.EXPORT_SECONDARY_SORT_FIELD, FieldName.AUTHOR); + prefs.put(JabRefPreferences.EXPORT_TERTIARY_SORT_FIELD, FieldName.EDITOR); prefs.putBoolean(JabRefPreferences.EXPORT_PRIMARY_SORT_DESCENDING, false); prefs.putBoolean(JabRefPreferences.EXPORT_SECONDARY_SORT_DESCENDING, false); prefs.putBoolean(JabRefPreferences.EXPORT_TERTIARY_SORT_DESCENDING, false); diff --git a/src/main/java/net/sf/jabref/model/DuplicateCheck.java b/src/main/java/net/sf/jabref/model/DuplicateCheck.java index d4653aefb41d..c99f7eb72226 100644 --- a/src/main/java/net/sf/jabref/model/DuplicateCheck.java +++ b/src/main/java/net/sf/jabref/model/DuplicateCheck.java @@ -26,6 +26,7 @@ import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FieldProperties; import net.sf.jabref.model.entry.InternalBibtexFields; @@ -61,10 +62,10 @@ public class DuplicateCheck { static { - DuplicateCheck.FIELD_WEIGHTS.put("author", 2.5); - DuplicateCheck.FIELD_WEIGHTS.put("editor", 2.5); - DuplicateCheck.FIELD_WEIGHTS.put("title", 3.); - DuplicateCheck.FIELD_WEIGHTS.put("journal", 2.); + DuplicateCheck.FIELD_WEIGHTS.put(FieldName.AUTHOR, 2.5); + DuplicateCheck.FIELD_WEIGHTS.put(FieldName.EDITOR, 2.5); + DuplicateCheck.FIELD_WEIGHTS.put(FieldName.TITLE, 3.); + DuplicateCheck.FIELD_WEIGHTS.put(FieldName.JOURNAL, 2.); } @@ -158,7 +159,7 @@ private static int compareSingleField(String field, BibEntry one, BibEntry two) return EQUAL; } return NOT_EQUAL; - } else if ("pages".equals(field)) { + } else if (FieldName.PAGES.equals(field)) { // Pages can be given with a variety of delimiters, "-", "--", " - ", " -- ". // We do a replace to harmonize these to a simple "-": // After this, a simple test for equality should be enough: @@ -168,7 +169,7 @@ private static int compareSingleField(String field, BibEntry one, BibEntry two) return EQUAL; } return NOT_EQUAL; - } else if ("journal".equals(field)) { + } else if (FieldName.JOURNAL.equals(field)) { // We do not attempt to harmonize abbreviation state of the journal names, // but we remove periods from the names in case they are abbreviated with // and without dots: diff --git a/src/main/java/net/sf/jabref/model/database/BibDatabase.java b/src/main/java/net/sf/jabref/model/database/BibDatabase.java index 20905246f84f..5ea3c93cd242 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabase.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabase.java @@ -46,6 +46,7 @@ import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.BibtexString; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.entry.MonthUtil; import net.sf.jabref.model.event.EntryAddedEvent; @@ -515,7 +516,7 @@ public static String getResolvedField(String field, BibEntry entry, BibDatabase // If this field is not set, and the entry has a crossref, try to look up the // field in the referred entry: Do not do this for the bibtex key. if (!result.isPresent() && (database != null) && !field.equals(BibEntry.KEY_FIELD)) { - Optional crossrefKey = entry.getFieldOptional("crossref"); + Optional crossrefKey = entry.getFieldOptional(FieldName.CROSSREF); if (crossrefKey.isPresent()) { Optional referred = database.getEntryByKey(crossrefKey.get()); if (referred.isPresent()) { diff --git a/src/main/java/net/sf/jabref/model/entry/BibEntry.java b/src/main/java/net/sf/jabref/model/entry/BibEntry.java index a25fb942570a..511373cb0cd3 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibEntry.java @@ -49,7 +49,6 @@ public class BibEntry implements Cloneable { public static final String TYPE_HEADER = "entrytype"; public static final String KEY_FIELD = "bibtexkey"; protected static final String ID_FIELD = "id"; - public static final String KEYWORDS_FIELD = "keywords"; private static final String DEFAULT_TYPE = "misc"; private String id; @@ -260,10 +259,10 @@ public Optional getFieldOrAlias(String name) { } // Finally, handle dates - if ("date".equals(name)) { - Optional year = getFieldOptional("year"); + if (FieldName.DATE.equals(name)) { + Optional year = getFieldOptional(FieldName.YEAR); if (year.isPresent()) { - MonthUtil.Month month = MonthUtil.getMonth(getFieldOptional("month").orElse("")); + MonthUtil.Month month = MonthUtil.getMonth(getFieldOptional(FieldName.MONTH).orElse("")); if (month.isValid()) { return Optional.of(year.get() + '-' + month.twoDigitNumber); } else { @@ -271,8 +270,8 @@ public Optional getFieldOrAlias(String name) { } } } - if ("year".equals(name) || "month".equals(name)) { - Optional date = getFieldOptional("date"); + if (FieldName.YEAR.equals(name) || FieldName.MONTH.equals(name)) { + Optional date = getFieldOptional(FieldName.DATE); if (!date.isPresent()) { return Optional.empty(); } @@ -303,10 +302,10 @@ public Date parse(String source, ParsePosition pos) { Date parsedDate = df.parse(date.get()); Calendar calendar = Calendar.getInstance(); calendar.setTime(parsedDate); - if ("year".equals(name)) { + if (FieldName.YEAR.equals(name)) { return Optional.of(Integer.toString(calendar.get(Calendar.YEAR))); } - if ("month".equals(name)) { + if (FieldName.MONTH.equals(name)) { return Optional.of(Integer.toString(calendar.get(Calendar.MONTH) + 1)); // Shift by 1 since in this calendar Jan = 0 } } catch (ParseException e) { @@ -317,7 +316,7 @@ public Date parse(String source, ParsePosition pos) { Date parsedDate = df.parse(date.get()); Calendar calendar = Calendar.getInstance(); calendar.setTime(parsedDate); - if ("year".equals(name)) { + if (FieldName.YEAR.equals(name)) { return Optional.of(Integer.toString(calendar.get(Calendar.YEAR))); } } catch (ParseException e2) { @@ -487,8 +486,8 @@ public void setGroupHit(boolean groupHit) { * Author1, Author2: Title (Year) */ public String getAuthorTitleYear(int maxCharacters) { - String[] s = new String[] {getFieldOptional("author").orElse("N/A"), getFieldOptional("title").orElse("N/A"), - getFieldOptional("year").orElse("N/A")}; + String[] s = new String[] {getFieldOptional(FieldName.AUTHOR).orElse("N/A"), getFieldOptional(FieldName.TITLE).orElse("N/A"), + getFieldOptional(FieldName.YEAR).orElse("N/A")}; String text = s[0] + ": \"" + s[1] + "\" (" + s[2] + ')'; if ((maxCharacters <= 0) || (text.length() <= maxCharacters)) { @@ -503,13 +502,13 @@ public String getAuthorTitleYear(int maxCharacters) { * @return will return the publication date of the entry or null if no year was found. */ public Optional getPublicationDate() { - if (!hasField("year")) { + if (!hasField(FieldName.YEAR)) { return Optional.empty(); } - Optional year = getFieldOptional("year"); + Optional year = getFieldOptional(FieldName.YEAR); - Optional monthString = getFieldOptional("month"); + Optional monthString = getFieldOptional(FieldName.MONTH); if (monthString.isPresent()) { MonthUtil.Month month = MonthUtil.getMonth(monthString.get()); if (month.isValid()) { @@ -539,12 +538,12 @@ public void setChanged(boolean changed) { public Optional putKeywords(Collection keywords, String separator) { Objects.requireNonNull(keywords); - Optional oldValue = this.getFieldOptional(KEYWORDS_FIELD); + Optional oldValue = this.getFieldOptional(FieldName.KEYWORDS); if (keywords.isEmpty()) { // Clear keyword field if (oldValue.isPresent()) { - return this.clearField(KEYWORDS_FIELD); + return this.clearField(FieldName.KEYWORDS); } else { return Optional.empty(); } @@ -552,7 +551,7 @@ public Optional putKeywords(Collection keywords, String sep // Set new keyword field String newValue = String.join(separator, keywords); - return this.setField(KEYWORDS_FIELD, newValue); + return this.setField(FieldName.KEYWORDS, newValue); } /** diff --git a/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java index 2af1d3a5343e..cd428e972c46 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java @@ -29,15 +29,15 @@ public class BibLatexEntryTypes { public static final BibLatexEntryType ARTICLE = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "editor", "series", "volume", "number", "eid", "issue", "pages", - "note", "issn", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + Arrays.asList("subtitle", FieldName.EDITOR, "series", FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.PAGES, + "note", FieldName.ISSN, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "journaltitle", "year/date"); - addAllOptional("translator", "annotator", "commentator", "subtitle", "titleaddon", "editor", "editora", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.JOURNALTITLE, "year/date"); + addAllOptional("translator", "annotator", "commentator", "subtitle", "titleaddon", FieldName.EDITOR, "editora", "editorb", "editorc", "journalsubtitle", "issuetitle", "issuesubtitle", "language", "origlanguage", - "series", "volume", "number", "eid", "issue", "month", "pages", "version", "note", "issn", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + "series", FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.MONTH, FieldName.PAGES, "version", "note", FieldName.ISSN, + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -54,18 +54,18 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType BOOK = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("editor", "subtitle", "titleaddon", "maintitle", - "mainsubtitle", "maintitleaddon", "volume", "edition", "publisher", "isbn", "chapter", "pages", - "pagetotal", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", + "mainsubtitle", "maintitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, + "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "year/date"); - addAllOptional("editor", "editora", "editorb", "editorc", "translator", "annotator", "commentator", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); + addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "language", "origlanguage", "volume", "part", "edition", "volumes", "series", - "number", "note", "publisher", "location", "isbn", "chapter", "pages", "pagetotal", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + "maintitleaddon", "language", "origlanguage", FieldName.VOLUME, "part", "edition", "volumes", "series", + FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -82,15 +82,15 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MVBOOK = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("editor", "subtitle", "titleaddon", "edition", "publisher", "isbn", "pagetotal", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList(FieldName.EDITOR, "subtitle", "titleaddon", "edition", FieldName.PUBLISHER, FieldName.ISBN, "pagetotal", + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "year/date"); - addAllOptional("editor", "editora", "editorb", "editorc", "translator", "annotator", "commentator", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); + addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "language", "origlanguage", - "edition", "volumes", "series", "number", "note", "publisher", "location", "isbn", "pagetotal", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + "edition", "volumes", "series", FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, "pagetotal", + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -107,18 +107,18 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType INBOOK = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList(Arrays - .asList("bookauthor", "editor", "subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "booksubtitle", "booktitleaddon", "volume", "edition", "publisher", "isbn", - "chapter", "pages", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .asList("bookauthor", FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", + "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, + "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "booktitle", "year/date"); - addAllOptional("bookauthor", "editor", "editora", "editorb", "editorc", "translator", "annotator", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", "year/date"); + addAllOptional("bookauthor", FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", "language", "origlanguage", - "volume", "part", "edition", "volumes", "series", "number", "note", "publisher", "location", "isbn", - "chapter", "pages", "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", + FieldName.VOLUME, "part", "edition", "volumes", "series", FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, + "chapter", FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -185,13 +185,13 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "howpublished", "chapter", - "pages", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author/editor", "title", "year/date"); + addAllRequired("author/editor", FieldName.TITLE, "year/date"); addAllOptional("subtitle", "titleaddon", "language", "howpublished", "type", "note", "location", "chapter", - "pages", "pagetotal", "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", - "url", "urldate"); + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", + FieldName.URL, "urldate"); } @Override @@ -209,17 +209,17 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", "maintitle", - "mainsubtitle", "maintitleaddon", "volume", "edition", "publisher", "isbn", "chapter", "pages", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + "mainsubtitle", "maintitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("editor", "title", "year/date"); + addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); addAllOptional("editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", - "language", "origlanguage", "volume", "part", "edition", "volumes", "series", "number", "note", - "publisher", "location", "isbn", "chapter", "pages", "pagetotal", "addendum", "pubstate", "doi", - "eprint", "eprintclass", "eprinttype", "url", "urldate"); + "language", "origlanguage", FieldName.VOLUME, "part", "edition", "volumes", "series", FieldName.NUMBER, "note", + FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, + "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -236,16 +236,16 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MVCOLLECTION = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", "edition", "publisher", "isbn", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", "edition", FieldName.PUBLISHER, FieldName.ISBN, + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("editor", "title", "year/date"); + addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); addAllOptional("editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", - "foreword", "afterword", "subtitle", "titleaddon", "language", "origlanguage", "edition", "volumes", "series", "number", "note", - "publisher", "location", "isbn", "pagetotal", "addendum", "pubstate", "doi", - "eprint", "eprintclass", "eprinttype", "url", "urldate"); + "foreword", "afterword", "subtitle", "titleaddon", "language", "origlanguage", "edition", "volumes", "series", FieldName.NUMBER, "note", + FieldName.PUBLISHER, "location", FieldName.ISBN, "pagetotal", "addendum", "pubstate", FieldName.DOI, + "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -263,17 +263,17 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections.unmodifiableList( Arrays.asList("translator", "subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "booksubtitle", "booktitleaddon", "volume", "edition", "publisher", "isbn", - "chapter", "pages", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, + "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "booktitle", "year/date"); - addAllOptional("editor", "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", "year/date"); + addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", - "booksubtitle", "booktitleaddon", "language", "origlanguage", "volume", "part", "edition", - "volumes", "series", "number", "note", "publisher", "location", "isbn", "chapter", "pages", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + "booksubtitle", "booktitleaddon", "language", "origlanguage", FieldName.VOLUME, "part", "edition", + "volumes", "series", FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -314,15 +314,15 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MANUAL = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "edition", "publisher", "isbn", - "chapter", "pages", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "edition", FieldName.PUBLISHER, FieldName.ISBN, + "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author/editor", "title", "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "edition", "type", "series", "number", "version", - "note", "organization", "publisher", "location", "isbn", "chapter", "pages", "pagetotal", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + addAllRequired("author/editor", FieldName.TITLE, "year/date"); + addAllOptional("subtitle", "titleaddon", "language", "edition", "type", "series", FieldName.NUMBER, "version", + "note", "organization", FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -340,14 +340,14 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "howpublished", "location", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author/editor", "title", "year/date"); + addAllRequired("author/editor", FieldName.TITLE, "year/date"); addAllOptional("subtitle", "titleaddon", "language", "howpublished", "type", "version", "note", - "organization", "location", "month", "addendum", "pubstate", "doi", "eprint", "eprintclass", - "eprinttype", "url", "urldate"); + "organization", "location", FieldName.MONTH, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", + "eprinttype", FieldName.URL, "urldate"); } @Override @@ -368,8 +368,8 @@ public List getPrimaryOptionalFields() { { - addAllRequired("author/editor", "title", "year/date", "url"); - addAllOptional("subtitle", "titleaddon", "language", "version", "note", "organization", "month", "addendum", "pubstate", "urldate"); + addAllRequired("author/editor", FieldName.TITLE, "year/date", FieldName.URL); + addAllOptional("subtitle", "titleaddon", "language", "version", "note", "organization", FieldName.MONTH, "addendum", "pubstate", "urldate"); } @Override @@ -386,13 +386,13 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType PATENT = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList(Arrays.asList("holder", - "subtitle", "titleaddon", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + "subtitle", "titleaddon", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "number", "year/date"); - addAllOptional("holder", "subtitle", "titleaddon", "type", "version", "location", "note", "month", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.NUMBER, "year/date"); + addAllOptional("holder", "subtitle", "titleaddon", "type", "version", "location", "note", FieldName.MONTH, + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -409,15 +409,15 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType PERIODICAL = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "issuetitle", "issuesubtitle", "issn", "doi", - "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "issuetitle", "issuesubtitle", FieldName.ISSN, FieldName.DOI, + "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("editor", "title", "year/date"); + addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); addAllOptional("editora", "editorb", "editorc", "subtitle", "issuetitle", "issuesubtitle", "language", - "series", "volume", "number", "issue", "month", "note", "issn", "addendum", "pubstate", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + "series", FieldName.VOLUME, FieldName.NUMBER, FieldName.ISSUE, FieldName.MONTH, "note", FieldName.ISSN, "addendum", "pubstate", + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -459,16 +459,16 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "eventtitle", "volume", "publisher", "isbn", "chapter", "pages", "pagetotal", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + "maintitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("title", "year/date"); - addAllOptional("editor", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "eventtitle", - "eventtitleaddon", "eventdate", "venue", "language", "volume", "part", "volumes", "series", "number", "note", - "organization", "publisher", "location", "month", "year", "isbn", "chapter", "pages", "pagetotal", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + addAllRequired(FieldName.TITLE, "year/date"); + addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "eventtitle", + "eventtitleaddon", "eventdate", "venue", "language", FieldName.VOLUME, "part", "volumes", "series", FieldName.NUMBER, "note", + "organization", FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.YEAR, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -486,16 +486,16 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "eventtitle", "volume", "publisher", "isbn", "chapter", "pages", "pagetotal", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + "maintitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("title", "year/date"); - addAllOptional("editor", "subtitle", "titleaddon", "eventtitle", - "eventtitleaddon", "eventdate", "venue", "language", "volumes", "series", "number", "note", - "organization", "publisher", "location", "month", "isbn", "pagetotal", - "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate"); + addAllRequired(FieldName.TITLE, "year/date"); + addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "eventtitle", + "eventtitleaddon", "eventdate", "venue", "language", "volumes", "series", FieldName.NUMBER, "note", + "organization", FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, "pagetotal", + "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -513,16 +513,16 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "booksubtitle", "booktitleaddon", "eventtitle", "volume", "publisher", "isbn", - "chapter", "pages", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + "maintitleaddon", "booksubtitle", "booktitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, + "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "booktitle", "year/date"); - addAllOptional("editor", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", - "booktitleaddon", "eventtitle", "eventtitleaddon", "eventdate", "venue", "language", "volume", "part", "volumes", - "series", "number", "note", "organization", "publisher", "location", "month", "isbn", - "chapter", "pages", "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", "year/date"); + addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", + "booktitleaddon", "eventtitle", "eventtitleaddon", "eventdate", "venue", "language", FieldName.VOLUME, "part", "volumes", + "series", FieldName.NUMBER, "note", "organization", FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, + "chapter", FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -612,15 +612,15 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType REPORT = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "number", "isrn", "chapter", - "pages", "pagetotal", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.NUMBER, "isrn", "chapter", + FieldName.PAGES, "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "type", "institution", "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "number", "version", "note", "location", "month", - "isrn", "chapter", "pages", "pagetotal", "addendum", "pubstate", "doi", "eprint", - "eprintclass", "eprinttype", "url", "urldate"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "type", "institution", "year/date"); + addAllOptional("subtitle", "titleaddon", "language", FieldName.NUMBER, "version", "note", "location", FieldName.MONTH, + "isrn", "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", + "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override @@ -636,7 +636,7 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType SET = new BibLatexEntryType() { { - addAllRequired("entryset", "crossref"); + addAllRequired("entryset", FieldName.CROSSREF); } @Override @@ -648,14 +648,14 @@ public String getName() { public static final BibLatexEntryType THESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "chapter", "pages", "pagetotal", - "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "chapter", FieldName.PAGES, "pagetotal", + FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "type", "institution", "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "note", "location", "month", "isbn", "chapter", - "pages", "pagetotal", "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "type", "institution", "year/date"); + addAllOptional("subtitle", "titleaddon", "language", "note", "location", FieldName.MONTH, FieldName.ISBN, "chapter", + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -673,13 +673,13 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType UNPUBLISHED = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", "howpublished", "pubstate", "url", "urldate")); + Arrays.asList("subtitle", "titleaddon", "howpublished", "pubstate", FieldName.URL, "urldate")); { - addAllRequired("author", "title", "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "howpublished", "note", "location", "month", - "addendum", "pubstate", "url", "urldate"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); + addAllOptional("subtitle", "titleaddon", "language", "howpublished", "note", "location", FieldName.MONTH, + "addendum", "pubstate", FieldName.URL, "urldate"); } @Override @@ -746,15 +746,15 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MASTERSTHESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "type", "chapter", "pages", - "pagetotal", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "type", "chapter", FieldName.PAGES, + "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { // Treated as alias of "THESIS", except "type" field is optional - addAllRequired("author", "title", "institution", "year/date"); - addAllOptional("type", "subtitle", "titleaddon", "language", "note", "location", "month", "isbn", "chapter", - "pages", "pagetotal", "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", "year/date"); + addAllOptional("type", "subtitle", "titleaddon", "language", "note", "location", FieldName.MONTH, FieldName.ISBN, "chapter", + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -772,15 +772,15 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType PHDTHESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "type", "chapter", "pages", - "pagetotal", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "type", "chapter", FieldName.PAGES, + "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { // Treated as alias of "THESIS", except "type" field is optional - addAllRequired("author", "title", "institution", "year/date"); - addAllOptional("type", "subtitle", "titleaddon", "language", "note", "location", "month", "isbn", "chapter", - "pages", "pagetotal", "addendum", "pubstate", "doi", "eprint", "eprintclass", "eprinttype", "url", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", "year/date"); + addAllOptional("type", "subtitle", "titleaddon", "language", "note", "location", FieldName.MONTH, FieldName.ISBN, "chapter", + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -798,16 +798,16 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType TECHREPORT = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", "type", "number", "isrn", "chapter", "pages", - "pagetotal", "doi", "eprint", "eprintclass", "eprinttype", "url", "urldate")); + Arrays.asList("subtitle", "titleaddon", "type", FieldName.NUMBER, "isrn", "chapter", FieldName.PAGES, + "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { // Treated as alias of "REPORT", except "type" field is optional - addAllRequired("author", "title", "institution", "year/date"); - addAllOptional("type", "subtitle", "titleaddon", "language", "number", "version", "note", "location", "month", - "isrn", "chapter", "pages", "pagetotal", "addendum", "pubstate", "doi", "eprint", - "eprintclass", "eprinttype", "url", "urldate"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", "year/date"); + addAllOptional("type", "subtitle", "titleaddon", "language", FieldName.NUMBER, "version", "note", "location", FieldName.MONTH, + "isrn", "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", + "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @Override diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java index 771786d5da79..0c906913a551 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java @@ -20,8 +20,8 @@ public class BibtexEntryTypes { public static final EntryType ARTICLE = new BibtexEntryType() { { - addAllRequired("author", "title", "journal", "year"); - addAllOptional("volume", "number", "pages", "month", "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.JOURNAL, FieldName.YEAR); + addAllOptional(FieldName.VOLUME, FieldName.NUMBER, FieldName.PAGES, FieldName.MONTH, "note"); } @Override @@ -39,8 +39,8 @@ public String getName() { public static final EntryType BOOK = new BibtexEntryType() { { - addAllRequired("title", "publisher", "year", "author/editor"); - addAllOptional("volume", "number", "series", "address", "edition", "month", "note"); + addAllRequired(FieldName.TITLE, FieldName.PUBLISHER, FieldName.YEAR, "author/editor"); + addAllOptional(FieldName.VOLUME, FieldName.NUMBER, "series", "address", "edition", FieldName.MONTH, "note"); } @Override @@ -58,8 +58,8 @@ public String getName() { public static final EntryType BOOKLET = new BibtexEntryType() { { - addAllRequired("title"); - addAllOptional("author", "howpublished", "address", "month", "year", "note"); + addAllRequired(FieldName.TITLE); + addAllOptional(FieldName.AUTHOR, "howpublished", "address", FieldName.MONTH, FieldName.YEAR, "note"); } @Override @@ -77,9 +77,9 @@ public String getName() { public static final EntryType CONFERENCE = new BibtexEntryType() { { - addAllRequired("author", "title", "booktitle", "year"); - addAllOptional("editor", "volume", "number", "series", "pages", "address", "month", "organization", - "publisher", "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", FieldName.YEAR); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", FieldName.PAGES, "address", FieldName.MONTH, "organization", + FieldName.PUBLISHER, "note"); } @Override @@ -97,8 +97,8 @@ public String getName() { public static final EntryType INBOOK = new BibtexEntryType() { { - addAllRequired("chapter/pages", "title", "publisher", "year", "author/editor"); - addAllOptional("volume", "number", "series", "type", "address", "edition", "month", "note"); + addAllRequired("chapter/pages", FieldName.TITLE, FieldName.PUBLISHER, FieldName.YEAR, "author/editor"); + addAllOptional(FieldName.VOLUME, FieldName.NUMBER, "series", "type", "address", "edition", FieldName.MONTH, "note"); } @Override @@ -115,9 +115,9 @@ public String getName() { public static final EntryType INCOLLECTION = new BibtexEntryType() { { - addAllRequired("author", "title", "booktitle", "publisher", "year"); - addAllOptional("editor", "volume", "number", "series", "type", "chapter", "pages", "address", "edition", - "month", "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", FieldName.PUBLISHER, FieldName.YEAR); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", "type", "chapter", FieldName.PAGES, "address", "edition", + FieldName.MONTH, "note"); } @Override @@ -135,9 +135,9 @@ public String getName() { public static final EntryType INPROCEEDINGS = new BibtexEntryType() { { - addAllRequired("author", "title", "booktitle", "year"); - addAllOptional("editor", "volume", "number", "series", "pages", "address", "month", "organization", - "publisher", "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", FieldName.YEAR); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", FieldName.PAGES, "address", FieldName.MONTH, "organization", + FieldName.PUBLISHER, "note"); } @Override @@ -154,8 +154,8 @@ public String getName() { public static final EntryType MANUAL = new BibtexEntryType() { { - addAllRequired("title"); - addAllOptional("author", "organization", "address", "edition", "month", "year", "note"); + addAllRequired(FieldName.TITLE); + addAllOptional(FieldName.AUTHOR, "organization", "address", "edition", FieldName.MONTH, FieldName.YEAR, "note"); } @Override @@ -173,8 +173,8 @@ public String getName() { public static final EntryType MASTERSTHESIS = new BibtexEntryType() { { - addAllRequired("author", "title", "school", "year"); - addAllOptional("type", "address", "month", "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "school", FieldName.YEAR); + addAllOptional("type", "address", FieldName.MONTH, "note"); } @Override @@ -192,7 +192,7 @@ public String getName() { public static final EntryType MISC = new BibtexEntryType() { { - addAllOptional("author", "title", "howpublished", "month", "year", "note"); + addAllOptional(FieldName.AUTHOR, FieldName.TITLE, "howpublished", FieldName.MONTH, FieldName.YEAR, "note"); } @Override @@ -210,8 +210,8 @@ public String getName() { public static final EntryType PHDTHESIS = new BibtexEntryType() { { - addAllRequired("author", "title", "school", "year"); - addAllOptional("type", "address", "month", "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "school", FieldName.YEAR); + addAllOptional("type", "address", FieldName.MONTH, "note"); } @Override @@ -229,8 +229,8 @@ public String getName() { public static final EntryType PROCEEDINGS = new BibtexEntryType() { { - addAllRequired("title", "year"); - addAllOptional("editor", "volume", "number", "series", "address", "publisher", "note", "month", + addAllRequired(FieldName.TITLE, FieldName.YEAR); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", "address", FieldName.PUBLISHER, "note", FieldName.MONTH, "organization"); } @@ -249,8 +249,8 @@ public String getName() { public static final EntryType TECHREPORT = new BibtexEntryType() { { - addAllRequired("author", "title", "institution", "year"); - addAllOptional("type", "number", "address", "month", "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", FieldName.YEAR); + addAllOptional("type", FieldName.NUMBER, "address", FieldName.MONTH, "note"); } @Override @@ -268,8 +268,8 @@ public String getName() { public static final EntryType UNPUBLISHED = new BibtexEntryType() { { - addAllRequired("author", "title", "note"); - addAllOptional("month", "year"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "note"); + addAllOptional(FieldName.MONTH, FieldName.YEAR); } @Override diff --git a/src/main/java/net/sf/jabref/model/entry/EntryConverter.java b/src/main/java/net/sf/jabref/model/entry/EntryConverter.java index 18910eb8fe5f..ad48e6e1d32c 100644 --- a/src/main/java/net/sf/jabref/model/entry/EntryConverter.java +++ b/src/main/java/net/sf/jabref/model/entry/EntryConverter.java @@ -20,9 +20,9 @@ public class EntryConverter { EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("address", "location"); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("annote", "annotation"); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("archiveprefix", "eprinttype"); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("journal", "journaltitle"); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.JOURNAL, FieldName.JOURNALTITLE); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("key", "sortkey"); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("pdf", "file"); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("pdf", FieldName.FILE); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("primaryclass", "eprintclass"); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("school", "institution"); diff --git a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java index cc0d189edf46..eaa96e409f12 100644 --- a/src/main/java/net/sf/jabref/model/entry/EntryUtil.java +++ b/src/main/java/net/sf/jabref/model/entry/EntryUtil.java @@ -51,7 +51,7 @@ public static Set getSeparatedKeywords(String keywordString) { * @return an List containing the keywords of the entry. An empty list if keywords are null or empty */ public static Set getSeparatedKeywords(BibEntry entry) { - return getSeparatedKeywords(entry.getFieldOptional(BibEntry.KEYWORDS_FIELD).orElse(null)); + return getSeparatedKeywords(entry.getFieldOptional(FieldName.KEYWORDS).orElse(null)); } /** diff --git a/src/main/java/net/sf/jabref/model/entry/FieldName.java b/src/main/java/net/sf/jabref/model/entry/FieldName.java new file mode 100644 index 000000000000..5de9895789d4 --- /dev/null +++ b/src/main/java/net/sf/jabref/model/entry/FieldName.java @@ -0,0 +1,31 @@ +package net.sf.jabref.model.entry; + + +public class FieldName { + + public static final String ABSTRACT = "abstract"; + public static final String AUTHOR = "author"; + public static final String CROSSREF = "crossref"; + public static final String DATE = "date"; + public static final String DOI = "doi"; + public static final String EDITOR = "editor"; + public static final String FILE = "file"; + public static final String FOLDER = "folder"; + public static final String ISBN = "isbn"; + public static final String ISSN = "issn"; + public static final String ISSUE = "issue"; + public static final String JOURNAL = "journal"; + public static final String JOURNALTITLE = "journaltitle"; + public static final String KEYWORDS = "keywords"; + public static final String MONTH = "month"; + public static final String NUMBER = "number"; + public static final String PAGES = "pages"; + public static final String PUBLISHER = "publisher"; + public static final String REVIEW = "review"; + public static final String TITLE = "title"; + public static final String URL = "url"; + public static final String VOLUME = "volume"; + public static final String YEAR = "year"; + + +} diff --git a/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java index abbd68e10375..fe0816f5b17e 100644 --- a/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java @@ -20,8 +20,8 @@ public class IEEETranEntryTypes { public static final EntryType ELECTRONIC = new BibtexEntryType() { { - addAllOptional("author", "month", "year", "title", "language", "howpublished", "organization", "address", - "note", "url"); + addAllOptional(FieldName.AUTHOR, FieldName.MONTH, FieldName.YEAR, FieldName.TITLE, "language", "howpublished", "organization", "address", + "note", FieldName.URL); } @@ -58,8 +58,8 @@ public String getName() { public static final EntryType PERIODICAL = new BibtexEntryType() { { - addAllRequired("title", "year"); - addAllOptional("editor", "language", "series", "volume", "number", "organization", "month", "note", "url"); + addAllRequired(FieldName.TITLE, FieldName.YEAR); + addAllOptional(FieldName.EDITOR, "language", "series", FieldName.VOLUME, FieldName.NUMBER, "organization", FieldName.MONTH, "note", FieldName.URL); } @Override @@ -77,9 +77,9 @@ public String getName() { public static final EntryType PATENT = new BibtexEntryType() { { - addAllRequired("nationality", "number", "year/yearfiled"); - addAllOptional("author", "title", "language", "assignee", "address", "type", "number", "day", "dayfiled", - "month", "monthfiled", "note", "url"); + addAllRequired("nationality", FieldName.NUMBER, "year/yearfiled"); + addAllOptional(FieldName.AUTHOR, FieldName.TITLE, "language", "assignee", "address", "type", FieldName.NUMBER, "day", "dayfiled", + FieldName.MONTH, "monthfiled", "note", FieldName.URL); } @Override @@ -97,9 +97,9 @@ public String getName() { public static final EntryType STANDARD = new BibtexEntryType() { { - addAllRequired("title", "organization/institution"); - addAllOptional("author", "language", "howpublished", "type", "number", "revision", "address", "month", - "year", "note", "url"); + addAllRequired(FieldName.TITLE, "organization/institution"); + addAllOptional(FieldName.AUTHOR, "language", "howpublished", "type", FieldName.NUMBER, "revision", "address", FieldName.MONTH, + FieldName.YEAR, "note", FieldName.URL); } @Override diff --git a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index ccb09d167c5a..4f8f4614e074 100644 --- a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -68,8 +68,8 @@ public class InternalBibtexFields { "ctlnames_show_etal", "ctlalt_stretch_factor"); public static final List IEEETRANBSTCTL_YES_NO_FIELDS = Arrays.asList("ctluse_article_number", "ctluse_paper", "ctluse_url", "ctluse_forced_etal", "ctluse_alt_spacing", "ctldash_repeated_names"); - public static final List BIBLATEX_DATE_FIELDS = Arrays.asList("date", "eventdate", "origdate", "urldate"); - public static final List BIBLATEX_PERSON_NAME_FIELDS = Arrays.asList("author", "editor", "editora", + public static final List BIBLATEX_DATE_FIELDS = Arrays.asList(FieldName.DATE, "eventdate", "origdate", "urldate"); + public static final List BIBLATEX_PERSON_NAME_FIELDS = Arrays.asList(FieldName.AUTHOR, FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "bookauthor", "holder", "shortauthor", "shorteditor", "sortname"); public static final List BIBLATEX_EDITOR_TYPE_FIELDS = Arrays.asList("editortype", "editoratype", @@ -93,42 +93,42 @@ private InternalBibtexFields(boolean serializeSpecialFields) { // but may be used by others that produce an annotated bibliography. // http://www.ecst.csuchico.edu/~jacobsd/bib/formats/bibtex.html add(new BibtexSingleField("annote", true, BibtexSingleField.LARGE_W)); - add(new BibtexSingleField("author", true, BibtexSingleField.MEDIUM_W, 280)); + add(new BibtexSingleField(FieldName.AUTHOR, true, BibtexSingleField.MEDIUM_W, 280)); add(new BibtexSingleField("booktitle", true, 175)); add(new BibtexSingleField("chapter", true, BibtexSingleField.SMALL_W)); - dummy = new BibtexSingleField("crossref", true, BibtexSingleField.SMALL_W); + dummy = new BibtexSingleField(FieldName.CROSSREF, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.CROSSREF)); add(dummy); add(new BibtexSingleField("edition", true, BibtexSingleField.SMALL_W)); - add(new BibtexSingleField("editor", true, BibtexSingleField.MEDIUM_W, 280)); + add(new BibtexSingleField(FieldName.EDITOR, true, BibtexSingleField.MEDIUM_W, 280)); add(new BibtexSingleField("howpublished", true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField("institution", true, BibtexSingleField.MEDIUM_W)); - dummy = new BibtexSingleField("journal", true, BibtexSingleField.SMALL_W); + dummy = new BibtexSingleField(FieldName.JOURNAL, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.JOURNAL_NAME)); add(dummy); - dummy = new BibtexSingleField("journaltitle", true, BibtexSingleField.SMALL_W); + dummy = new BibtexSingleField(FieldName.JOURNALTITLE, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.JOURNAL_NAME)); add(dummy); add(new BibtexSingleField("key", true)); - dummy = new BibtexSingleField("month", true, BibtexSingleField.SMALL_W); + dummy = new BibtexSingleField(FieldName.MONTH, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.MONTH)); add(dummy); add(new BibtexSingleField("note", true, BibtexSingleField.MEDIUM_W)); - add(new BibtexSingleField("number", true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); + add(new BibtexSingleField(FieldName.NUMBER, true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); add(new BibtexSingleField("organization", true, BibtexSingleField.MEDIUM_W)); - add(new BibtexSingleField("pages", true, BibtexSingleField.SMALL_W)); - add(new BibtexSingleField("publisher", true, BibtexSingleField.MEDIUM_W)); + add(new BibtexSingleField(FieldName.PAGES, true, BibtexSingleField.SMALL_W)); + add(new BibtexSingleField(FieldName.PUBLISHER, true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField("school", true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField("series", true, BibtexSingleField.SMALL_W)); - add(new BibtexSingleField("title", true, 400)); + add(new BibtexSingleField(FieldName.TITLE, true, 400)); dummy = new BibtexSingleField("type", true, BibtexSingleField.SMALL_W); dummy.getExtras().add(FieldProperties.TYPE); add(dummy); add(new BibtexSingleField("language", true, BibtexSingleField.SMALL_W)); - add(new BibtexSingleField("volume", true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); - add(new BibtexSingleField("year", true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); + add(new BibtexSingleField(FieldName.VOLUME, true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); + add(new BibtexSingleField(FieldName.YEAR, true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); // custom fields not displayed at editor, but as columns in the UI dummy = new BibtexSingleField(SpecialFieldsUtils.FIELDNAME_RANKING, false); @@ -179,12 +179,12 @@ private InternalBibtexFields(boolean serializeSpecialFields) { dummy.setPrivate(); add(dummy); - dummy = new BibtexSingleField("doi", true, BibtexSingleField.SMALL_W); + dummy = new BibtexSingleField(FieldName.DOI, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.DOI)); add(dummy); add(new BibtexSingleField("eid", true, BibtexSingleField.SMALL_W)); - dummy = new BibtexSingleField("date", true); + dummy = new BibtexSingleField(FieldName.DATE, true); dummy.setPrivate(); add(dummy); @@ -192,16 +192,16 @@ private InternalBibtexFields(boolean serializeSpecialFields) { // additional fields ------------------------------------------------------ add(new BibtexSingleField("location", false)); - add(new BibtexSingleField("abstract", false, BibtexSingleField.LARGE_W, 400)); + add(new BibtexSingleField(FieldName.ABSTRACT, false, BibtexSingleField.LARGE_W, 400)); - dummy = new BibtexSingleField("url", false, BibtexSingleField.SMALL_W); + dummy = new BibtexSingleField(FieldName.URL, false, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.EXTERNAL)); add(dummy); add(new BibtexSingleField("comment", false, BibtexSingleField.MEDIUM_W)); - add(new BibtexSingleField("keywords", false, BibtexSingleField.SMALL_W)); + add(new BibtexSingleField(FieldName.KEYWORDS, false, BibtexSingleField.SMALL_W)); - dummy = new BibtexSingleField(Globals.FILE_FIELD, false); + dummy = new BibtexSingleField(FieldName.FILE, false); dummy.setExtras(EnumSet.of(FieldProperties.FILE_EDITOR)); add(dummy); diff --git a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java index 53fbc520690d..0b8e1e778676 100644 --- a/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java +++ b/src/main/java/net/sf/jabref/pdfimport/PdfImporter.java @@ -48,6 +48,7 @@ import net.sf.jabref.model.database.KeyCollisionException; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import net.sf.jabref.preferences.JabRefPreferences; @@ -215,7 +216,7 @@ private void doXMPImport(String fileName, List res) { tm.addEntry(0, new FileListEntry(toLink.getName(), FileUtil.shortenFileName(toLink, dirsS).getPath(), ExternalFileTypes.getInstance().getExternalFileTypeByName("PDF"))); - entry.setField(Globals.FILE_FIELD, tm.getStringRepresentation()); + entry.setField(FieldName.FILE, tm.getStringRepresentation()); res.add(entry); } diff --git a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java index dd299ab52b42..255af2dd4a6d 100644 --- a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java @@ -76,8 +76,10 @@ import net.sf.jabref.logic.util.VersionPreferences; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.CustomEntryType; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.specialfields.SpecialFieldsUtils; @@ -358,13 +360,13 @@ public class JabRefPreferences { CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); List activeFormatterCleanups = new ArrayList<>(); - activeFormatterCleanups.add(new FieldFormatterCleanup("pages", new NormalizePagesFormatter())); - activeFormatterCleanups.add(new FieldFormatterCleanup("date", new NormalizeDateFormatter())); - activeFormatterCleanups.add(new FieldFormatterCleanup("month", new NormalizeMonthFormatter())); - activeFormatterCleanups.add(new FieldFormatterCleanup("title", new ProtectTermsFormatter())); - activeFormatterCleanups.add(new FieldFormatterCleanup("title", new UnitsToLatexFormatter())); - activeFormatterCleanups.add(new FieldFormatterCleanup("title", new LatexCleanupFormatter())); - activeFormatterCleanups.add(new FieldFormatterCleanup("title", new HtmlToLatexFormatter())); + activeFormatterCleanups.add(new FieldFormatterCleanup(FieldName.PAGES, new NormalizePagesFormatter())); + activeFormatterCleanups.add(new FieldFormatterCleanup(FieldName.DATE, new NormalizeDateFormatter())); + activeFormatterCleanups.add(new FieldFormatterCleanup(FieldName.MONTH, new NormalizeMonthFormatter())); + activeFormatterCleanups.add(new FieldFormatterCleanup(FieldName.TITLE, new ProtectTermsFormatter())); + activeFormatterCleanups.add(new FieldFormatterCleanup(FieldName.TITLE, new UnitsToLatexFormatter())); + activeFormatterCleanups.add(new FieldFormatterCleanup(FieldName.TITLE, new LatexCleanupFormatter())); + activeFormatterCleanups.add(new FieldFormatterCleanup(FieldName.TITLE, new HtmlToLatexFormatter())); FieldFormatterCleanups formatterCleanups = new FieldFormatterCleanups(true, activeFormatterCleanups); CLEANUP_DEFAULT_PRESET = new CleanupPreset(EnumSet.complementOf(deactivedJobs), formatterCleanups); } @@ -535,11 +537,11 @@ private JabRefPreferences() { defaults.put(LANGUAGE, Locale.getDefault().getLanguage()); // Sorting preferences - defaults.put(TABLE_PRIMARY_SORT_FIELD, "author"); + defaults.put(TABLE_PRIMARY_SORT_FIELD, FieldName.AUTHOR); defaults.put(TABLE_PRIMARY_SORT_DESCENDING, Boolean.FALSE); - defaults.put(TABLE_SECONDARY_SORT_FIELD, "year"); + defaults.put(TABLE_SECONDARY_SORT_FIELD, FieldName.YEAR); defaults.put(TABLE_SECONDARY_SORT_DESCENDING, Boolean.TRUE); - defaults.put(TABLE_TERTIARY_SORT_FIELD, "title"); + defaults.put(TABLE_TERTIARY_SORT_FIELD, FieldName.TITLE); defaults.put(TABLE_TERTIARY_SORT_DESCENDING, Boolean.FALSE); defaults.put(REFORMAT_FILE_ON_SAVE_AND_EXPORT, Boolean.FALSE); @@ -549,11 +551,11 @@ private JabRefPreferences() { defaults.put(EXPORT_IN_SPECIFIED_ORDER, Boolean.FALSE); // export order: if EXPORT_IN_SPECIFIED_ORDER, then use following criteria - defaults.put(EXPORT_PRIMARY_SORT_FIELD, "bibtexkey"); + defaults.put(EXPORT_PRIMARY_SORT_FIELD, BibEntry.KEY_FIELD); defaults.put(EXPORT_PRIMARY_SORT_DESCENDING, Boolean.FALSE); - defaults.put(EXPORT_SECONDARY_SORT_FIELD, "author"); + defaults.put(EXPORT_SECONDARY_SORT_FIELD, FieldName.AUTHOR); defaults.put(EXPORT_SECONDARY_SORT_DESCENDING, Boolean.FALSE); - defaults.put(EXPORT_TERTIARY_SORT_FIELD, "title"); + defaults.put(EXPORT_TERTIARY_SORT_FIELD, FieldName.TITLE); defaults.put(EXPORT_TERTIARY_SORT_DESCENDING, Boolean.TRUE); defaults.put(NEWLINE, System.lineSeparator()); @@ -614,7 +616,7 @@ private JabRefPreferences() { defaults.put(GROUP_INTERSECT_SELECTIONS, Boolean.TRUE); defaults.put(GROUP_INVERT_SELECTIONS, Boolean.FALSE); defaults.put(GROUP_SHOW_OVERLAPPING, Boolean.FALSE); - defaults.put(GROUPS_DEFAULT_FIELD, "keywords"); + defaults.put(GROUPS_DEFAULT_FIELD, FieldName.KEYWORDS); defaults.put(GROUP_SHOW_ICONS, Boolean.TRUE); defaults.put(GROUP_SHOW_DYNAMIC, Boolean.TRUE); defaults.put(GROUP_EXPAND_TREE, Boolean.TRUE); @@ -769,7 +771,7 @@ private JabRefPreferences() { // TODO: Currently not possible to edit this setting: defaults.put(PREVIEW_PRINT_BUTTON, Boolean.FALSE); - defaults.put(DO_NOT_RESOLVE_STRINGS_FOR, "url"); + defaults.put(DO_NOT_RESOLVE_STRINGS_FOR, FieldName.URL); defaults.put(RESOLVE_STRINGS_ALL_FIELDS, Boolean.FALSE); defaults.put(NON_WRAPPABLE_FIELDS, "pdf;ps;url;doi;file"); defaults.put(GENERATE_KEYS_AFTER_INSPECTION, Boolean.TRUE); @@ -912,11 +914,11 @@ public void setLanguageDependentDefaultValues() { + "comment;owner;timestamp"); // Entry editor tab 1: - defaults.put(CUSTOM_TAB_FIELDS + "_def1", "abstract"); + defaults.put(CUSTOM_TAB_FIELDS + "_def1", FieldName.ABSTRACT); defaults.put(CUSTOM_TAB_NAME + "_def1", Localization.lang("Abstract")); // Entry editor tab 2: Review Field - used for research comments, etc. - defaults.put(CUSTOM_TAB_FIELDS + "_def2", "review"); + defaults.put(CUSTOM_TAB_FIELDS + "_def2", FieldName.REVIEW); defaults.put(CUSTOM_TAB_NAME + "_def2", Localization.lang("Review")); defaults.put(EMAIL_SUBJECT, Localization.lang("References")); diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java index b5174a5485dc..94a042772a36 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldUpdateListener.java @@ -20,6 +20,7 @@ import net.sf.jabref.JabRefGUI; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.event.FieldChangedEvent; import com.google.common.eventbus.Subscribe; @@ -43,7 +44,7 @@ public void listen(FieldChangedEvent fieldChangedEvent) { // e.g., "keyword = {prio1}, priority = {prio2}" and a change at keyword to prio3 would not succeed. SwingUtilities.invokeLater(() -> { NamedCompound compound = new NamedCompound("SpecialFieldSync"); - if ("keywords".equals(fieldName)) { + if (FieldName.KEYWORDS.equals(fieldName)) { SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, compound); SwingUtilities .invokeLater(() -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); diff --git a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java index 940cd3302b13..318e887f8aac 100644 --- a/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java +++ b/src/main/java/net/sf/jabref/specialfields/SpecialFieldsUtils.java @@ -27,9 +27,9 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryUtil; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; -import static net.sf.jabref.model.entry.BibEntry.KEYWORDS_FIELD; public class SpecialFieldsUtils { @@ -163,7 +163,7 @@ private static void importKeywordsForField(Set keywordList, SpecialField * @param ce indicates the undo named compound. May be null */ public static void syncSpecialFieldsFromKeywords(BibEntry be, NamedCompound ce) { - if (!be.hasField(KEYWORDS_FIELD)) { + if (!be.hasField(FieldName.KEYWORDS)) { return; } Set keywordList = EntryUtil.getSeparatedKeywords(be); diff --git a/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java b/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java index 0c00382b4a7e..2774968f898c 100644 --- a/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java +++ b/src/test/java/net/sf/jabref/model/entry/EntryUtilTest.java @@ -28,7 +28,7 @@ public void getSeparatedKeywords() { public void getSeparatedKeywordsEntry() { String keywords = "w1, w2a w2b, w3"; BibEntry entry = new BibEntry(); - entry.setField(BibEntry.KEYWORDS_FIELD, keywords); + entry.setField(FieldName.KEYWORDS, keywords); Set separatedKeywords = EntryUtil.getSeparatedKeywords(entry); Assert.assertEquals(new LinkedHashSet<>(Arrays.asList("w1", "w2a w2b", "w3")), separatedKeywords); } From 2989a1b9345e3ae58b2728caa28055e572cf3ad3 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 22 Jul 2016 09:59:13 +0200 Subject: [PATCH 260/268] More fields added to FieldName (#1614) * More fields added to FieldName * Some Medline fixes --- .../gui/openoffice/StyleSelectDialog.java | 2 +- .../importer/fetcher/DiVAtoBibTeXFetcher.java | 4 +- .../sf/jabref/importer/fetcher/GVKParser.java | 10 +- .../importer/fetcher/IEEEXploreFetcher.java | 6 +- .../fileformat/BiblioscapeImporter.java | 12 +- .../importer/fileformat/CopacImporter.java | 4 +- .../importer/fileformat/EndnoteImporter.java | 12 +- .../importer/fileformat/FreeCiteImporter.java | 14 +- .../importer/fileformat/IsiImporter.java | 2 +- .../importer/fileformat/JSONEntryParser.java | 2 +- .../importer/fileformat/MedlineImporter.java | 57 +++++---- .../fileformat/MedlinePlainImporter.java | 13 +- .../importer/fileformat/OvidImporter.java | 8 +- .../fileformat/PdfContentImporter.java | 4 +- .../importer/fileformat/RepecNepImporter.java | 2 +- .../importer/fileformat/RisImporter.java | 10 +- .../fileformat/SilverPlatterImporter.java | 2 +- .../sf/jabref/logic/cleanup/DoiCleanup.java | 2 +- .../exporter/FieldFormatterCleanups.java | 2 +- .../jabref/logic/exporter/OOCalcDatabase.java | 20 +-- .../exporter/OpenDocumentRepresentation.java | 20 +-- .../logic/integrity/IntegrityCheck.java | 4 +- .../logic/labelpattern/LabelPatternUtil.java | 4 +- .../net/sf/jabref/logic/mods/MODSEntry.java | 2 +- .../jabref/logic/msbib/BibTeXConverter.java | 10 +- .../sf/jabref/logic/msbib/MSBibConverter.java | 16 +-- .../sf/jabref/logic/msbib/MSBibMapping.java | 20 +-- .../sf/jabref/logic/xmp/XMPSchemaBibtex.java | 2 +- .../model/entry/BibLatexEntryTypes.java | 120 +++++++++--------- .../jabref/model/entry/BibtexEntryTypes.java | 48 +++---- .../sf/jabref/model/entry/EntryConverter.java | 4 +- .../net/sf/jabref/model/entry/FieldName.java | 13 +- .../model/entry/IEEETranEntryTypes.java | 14 +- .../model/entry/InternalBibtexFields.java | 20 +-- 34 files changed, 247 insertions(+), 238 deletions(-) diff --git a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java index 89bc47ee2e21..870013fa67b4 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/StyleSelectDialog.java @@ -380,7 +380,7 @@ private void setupPrevEntry() { prevEntry.setField(FieldName.YEAR, "2008"); prevEntry.setField(FieldName.JOURNAL, "BibTeX journal"); prevEntry.setField(FieldName.PUBLISHER, "JabRef publishing"); - prevEntry.setField("address", "Trondheim"); + prevEntry.setField(FieldName.ADDRESS, "Trondheim"); prevEntry.setField("www", "https://github.com/JabRef"); } diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java index 49e91cda1c71..6695f0d53247 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java @@ -109,8 +109,8 @@ public boolean processQuery(String query, ImportInspector inspector, OutputPrint entry.setField(FieldName.TITLE, title); }); - entry.getFieldOptional("institution").ifPresent( - institution -> entry.setField("institution", new UnicodeToLatexFormatter().format(institution))); + entry.getFieldOptional(FieldName.INSTITUTION).ifPresent( + institution -> entry.setField(FieldName.INSTITUTION, new UnicodeToLatexFormatter().format(institution))); // Do not use the provided key // entry.clearField(InternalBibtexFields.KEY_FIELD); inspector.addEntry(entry); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java index 905c33fcc31c..5da796ac4ed9 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -391,13 +391,13 @@ private BibEntry parseEntry(Element e) { result.setField(FieldName.YEAR, year); } if (address != null) { - result.setField("address", address); + result.setField(FieldName.ADDRESS, address); } if (series != null) { - result.setField("series", series); + result.setField(FieldName.SERIES, series); } if (edition != null) { - result.setField("edition", edition); + result.setField(FieldName.EDITION, edition); } if (isbn != null) { result.setField(FieldName.ISBN, isbn); @@ -427,13 +427,13 @@ private BibEntry parseEntry(Element e) { result.setField(FieldName.URL, url); } if (note != null) { - result.setField("note", note); + result.setField(FieldName.NOTE, note); } if ("article".equals(entryType) && (journal != null)) { result.setField(FieldName.JOURNAL, journal); } else if ("incollection".equals(entryType) && (booktitle != null)) { - result.setField("booktitle", booktitle); + result.setField(FieldName.BOOKTITLE, booktitle); } return result; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index d3484928d0d3..f76691ee4aa3 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -373,9 +373,9 @@ private BibEntry cleanup(BibEntry entry) { String sourceField = ""; if ("article".equals(type)) { sourceField = FieldName.JOURNAL; - entry.clearField("booktitle"); + entry.clearField(FieldName.BOOKTITLE); } else if ("inproceedings".equals(type)) { - sourceField = "booktitle"; + sourceField = FieldName.BOOKTITLE; } if (entry.hasField(sourceField)) { String fullName = entry.getField(sourceField); @@ -393,7 +393,7 @@ private BibEntry cleanup(BibEntry entry) { if (parts.length == 3) { fullName += parts[2]; } - String note = entry.getField("note"); + String note = entry.getField(FieldName.NOTE); if ("Early Access".equals(note)) { entry.setField(FieldName.YEAR, "to be published"); entry.clearField(FieldName.MONTH); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java index 07422b6344a7..e125210f8fc5 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java @@ -119,7 +119,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { comments .add("Secondary Authors: " + entry.getValue()); } else if ("NT".equals(entry.getKey())) { - hm.put("note", entry + hm.put(FieldName.NOTE, entry .getValue().toString()); } else if ("PB".equals(entry.getKey())) { hm.put(FieldName.PUBLISHER, entry @@ -131,7 +131,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { comments .add("Tertiary Title: " + entry.getValue()); } else if ("ED".equals(entry.getKey())) { - hm.put("edition", entry + hm.put(FieldName.EDITION, entry .getValue().toString()); } else if ("TW".equals(entry.getKey())) { type[1] = entry.getValue() @@ -152,7 +152,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { address = entry.getValue() .toString(); } else if ("LG".equals(entry.getKey())) { - hm.put("language", entry + hm.put(FieldName.LANGUAGE, entry .getValue().toString()); } else if ("CO".equals(entry.getKey())) { country = entry.getValue() @@ -239,14 +239,14 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } } else if ("inbook".equals(bibtexType)) { if (titleST != null) { - hm.put("booktitle", titleST); + hm.put(FieldName.BOOKTITLE, titleST); } if (titleTI != null) { hm.put(FieldName.TITLE, titleTI); } } else { if (titleST != null) { - hm.put("booktitle", titleST); // should not + hm.put(FieldName.BOOKTITLE, titleST); // should not } // happen, I // think @@ -262,7 +262,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { // concatenate address and country if (address != null) { - hm.put("address", address + (country == null ? "" : ", " + country)); + hm.put(FieldName.ADDRESS, address + (country == null ? "" : ", " + country)); } if (!comments.isEmpty()) { // set comment if present diff --git a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java index ded1972dc614..4df397a8d8b8 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/CopacImporter.java @@ -132,13 +132,13 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } else if ("PU- ".equals(code)) { setOrAppend(b, FieldName.PUBLISHER, line.substring(4).trim(), ", "); } else if ("SE- ".equals(code)) { - setOrAppend(b, "series", line.substring(4).trim(), ", "); + setOrAppend(b, FieldName.SERIES, line.substring(4).trim(), ", "); } else if ("IS- ".equals(code)) { setOrAppend(b, FieldName.ISBN, line.substring(4).trim(), ", "); } else if ("KW- ".equals(code)) { setOrAppend(b, FieldName.KEYWORDS, line.substring(4).trim(), ", "); } else if ("NT- ".equals(code)) { - setOrAppend(b, "note", line.substring(4).trim(), ", "); + setOrAppend(b, FieldName.NOTE, line.substring(4).trim(), ", "); } else if ("PD- ".equals(code)) { setOrAppend(b, "physicaldimensions", line.substring(4).trim(), ", "); } else if ("DT- ".equals(code)) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java index 44a5b9e5a9fd..2ce04c2abb3d 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/EndnoteImporter.java @@ -172,9 +172,9 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { type = "misc"; // } } else if ("7".equals(prefix)) { - hm.put("edition", val); + hm.put(FieldName.EDITION, val); } else if ("C".equals(prefix)) { - hm.put("address", val); + hm.put(FieldName.ADDRESS, val); } else if ("D".equals(prefix)) { hm.put(FieldName.YEAR, val); } else if ("8".equals(prefix)) { @@ -189,14 +189,14 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { if ("article".equals(type)) { hm.put(FieldName.JOURNAL, val); } else if ("book".equals(type) || "inbook".equals(type)) { - hm.put("series", val); + hm.put(FieldName.SERIES, val); } else { /* type = inproceedings */ - hm.put("booktitle", val); + hm.put(FieldName.BOOKTITLE, val); } } else if ("I".equals(prefix)) { if ("phdthesis".equals(type)) { - hm.put("school", val); + hm.put(FieldName.SCHOOL, val); } else { hm.put(FieldName.PUBLISHER, val); } @@ -222,7 +222,7 @@ else if ("P".equals(prefix)) { String[] tokens = val.split("\\s"); artnum = tokens[1]; } else { - hm.put("note", val); + hm.put(FieldName.NOTE, val); } } else if ("K".equals(prefix)) { hm.put(FieldName.KEYWORDS, val); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index 35d53738b8f9..83a1fdde592a 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -167,24 +167,24 @@ public ParserResult importEntries(String text) { // the content of the "tech" field seems to contain the number of the technical report e.setField(FieldName.NUMBER, parser.getElementText()); } else if (FieldName.DOI.equals(ln) - || "institution".equals(ln) + || FieldName.INSTITUTION.equals(ln) || "location".equals(ln) || FieldName.NUMBER.equals(ln) - || "note".equals(ln) + || FieldName.NOTE.equals(ln) || FieldName.TITLE.equals(ln) || FieldName.PAGES.equals(ln) || FieldName.PUBLISHER.equals(ln) || FieldName.VOLUME.equals(ln) || FieldName.YEAR.equals(ln)) { e.setField(ln, parser.getElementText()); - } else if ("booktitle".equals(ln)) { + } else if (FieldName.BOOKTITLE.equals(ln)) { String booktitle = parser.getElementText(); if (booktitle.startsWith("In ")) { // special treatment for parsing of // "In proceedings of..." references booktitle = booktitle.substring(3); } - e.setField("booktitle", booktitle); + e.setField(FieldName.BOOKTITLE, booktitle); } else if ("raw_string".equals(ln)) { // raw input string is ignored } else { @@ -200,13 +200,13 @@ public ParserResult importEntries(String text) { if (noteSB.length() > 0) { String note; - if (e.hasField("note")) { + if (e.hasField(FieldName.NOTE)) { // "note" could have been set during the parsing as FreeCite also returns "note" - note = e.getFieldOptional("note").get().concat(Globals.NEWLINE).concat(noteSB.toString()); + note = e.getFieldOptional(FieldName.NOTE).get().concat(Globals.NEWLINE).concat(noteSB.toString()); } else { note = noteSB.toString(); } - e.setField("note", note); + e.setField(FieldName.NOTE, note); } // type has been derived from "genre" diff --git a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java index b1c3835b1536..8658aef5afca 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/IsiImporter.java @@ -227,7 +227,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { Type = "inproceedings"; } } else if ("JO".equals(beg)) { - hm.put("booktitle", value); + hm.put(FieldName.BOOKTITLE, value); } else if ("AU".equals(beg)) { String author = IsiImporter.isiAuthorsConvert(value.replace("EOLEOL", " and ")); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java index badc3fdb7667..d929458977a9 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/JSONEntryParser.java @@ -171,7 +171,7 @@ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { } else { // Probably book chapter or from proceeding, go for book chapter entry.setType("incollection"); - nametype = "booktitle"; + nametype = FieldName.BOOKTITLE; entry.setField(FieldName.ISBN, isbn); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java index 1eb6b5880122..92ff94aa8597 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlineImporter.java @@ -80,6 +80,7 @@ import net.sf.jabref.importer.fileformat.medline.Text; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.IdGenerator; import com.google.common.base.Joiner; @@ -261,11 +262,11 @@ private void addBookInformation(HashMap fields, Book book) { if (book.getPublisher() != null) { Publisher publisher = book.getPublisher(); putIfValueNotNull(fields, "publocation", publisher.getPublisherLocation()); - putStringFromSerializableList(fields, "publisher", publisher.getPublisherName().getContent()); + putStringFromSerializableList(fields, FieldName.PUBLISHER, publisher.getPublisherName().getContent()); } if (book.getBookTitle() != null) { BookTitle title = book.getBookTitle(); - putStringFromSerializableList(fields, "title", title.getContent()); + putStringFromSerializableList(fields, FieldName.TITLE, title.getContent()); } if (book.getPubDate() != null) { addPubDate(fields, book.getPubDate()); @@ -282,8 +283,8 @@ private void addBookInformation(HashMap fields, Book book) { } } - putIfValueNotNull(fields, "volume", book.getVolume()); - putIfValueNotNull(fields, "edition", book.getEdition()); + putIfValueNotNull(fields, FieldName.VOLUME, book.getVolume()); + putIfValueNotNull(fields, FieldName.EDITION, book.getEdition()); putIfValueNotNull(fields, "medium", book.getMedium()); putIfValueNotNull(fields, "reportnumber", book.getReportNumber()); @@ -293,7 +294,7 @@ private void addBookInformation(HashMap fields, Book book) { } } if (book.getIsbn() != null) { - fields.put("isbn", join(book.getIsbn(), ", ")); + fields.put(FieldName.ISBN, join(book.getIsbn(), ", ")); } } @@ -406,7 +407,7 @@ private void addNotes(HashMap fields, List generalN notes.add(note.getContent()); } } - fields.put("note", join(notes, ", ")); + fields.put(FieldName.NOTE, join(notes, ", ")); } private void addInvestigators(HashMap fields, InvestigatorList investigatorList) { @@ -452,14 +453,14 @@ private void addKeyWords(HashMap fields, List allKe } } //Check whether MeshHeadingList exist or not - if (fields.get("keywords") == null) { - fields.put("keywords", join(keywordStrings, KEYWORD_SEPARATOR)); + if (fields.get(FieldName.KEYWORDS) == null) { + fields.put(FieldName.KEYWORDS, join(keywordStrings, KEYWORD_SEPARATOR)); } else { if (keywordStrings.size() > 0) { //if it exists, combine the MeshHeading with the keywords String result = join(keywordStrings, "; "); - result = fields.get("keywords") + KEYWORD_SEPARATOR + result; - fields.put("keywords", result); + result = fields.get(FieldName.KEYWORDS) + KEYWORD_SEPARATOR + result; + fields.put(FieldName.KEYWORDS, result); } } } @@ -473,7 +474,7 @@ private void addOtherId(HashMap fields, List otherID) { } private void addPersonalNames(HashMap fields, PersonalNameSubjectList personalNameSubjectList) { - if (fields.get("author") == null) { + if (fields.get(FieldName.AUTHOR) == null) { //if no authors appear, then add the personal names as authors List personalNames = new ArrayList<>(); if (personalNameSubjectList.getPersonalNameSubject() != null) { @@ -485,7 +486,7 @@ private void addPersonalNames(HashMap fields, PersonalNameSubjec } personalNames.add(name); } - fields.put("author", join(personalNames, " and ")); + fields.put(FieldName.AUTHOR, join(personalNames, " and ")); } } } @@ -501,7 +502,7 @@ private void addMeashHeading(HashMap fields, MeshHeadingList mes } keywords.add(result); } - fields.put("keywords", join(keywords, KEYWORD_SEPARATOR)); + fields.put(FieldName.KEYWORDS, join(keywords, KEYWORD_SEPARATOR)); } private void addGeneSymbols(HashMap fields, GeneSymbolList geneSymbolList) { @@ -523,19 +524,19 @@ private void addArticleInformation(HashMap fields, List for (Object object : content) { if (object instanceof Journal) { Journal journal = (Journal) object; - putIfValueNotNull(fields, "journal", journal.getTitle()); + putIfValueNotNull(fields, FieldName.JOURNAL, journal.getTitle()); ISSN issn = journal.getISSN(); - putIfValueNotNull(fields, "issn", issn.getContent()); + putIfValueNotNull(fields, FieldName.ISSN, issn.getContent()); JournalIssue journalIssue = journal.getJournalIssue(); - putIfValueNotNull(fields, "volume", journalIssue.getVolume()); - putIfValueNotNull(fields, "issue", journalIssue.getIssue()); + putIfValueNotNull(fields, FieldName.VOLUME, journalIssue.getVolume()); + putIfValueNotNull(fields, FieldName.ISSUE, journalIssue.getIssue()); addPubDate(fields, journalIssue.getPubDate()); } else if (object instanceof ArticleTitle) { ArticleTitle articleTitle = (ArticleTitle) object; - fields.put("title", StringUtil.stripBrackets(articleTitle.getContent().toString())); + fields.put(FieldName.TITLE, StringUtil.stripBrackets(articleTitle.getContent().toString())); } else if (object instanceof Pagination) { Pagination pagination = (Pagination) object; addPagination(fields, pagination); @@ -553,8 +554,8 @@ private void addArticleInformation(HashMap fields, List } private void addElocationID(HashMap fields, ELocationID eLocationID) { - if ("doi".equals(eLocationID.getEIdType())) { - fields.put("doi", eLocationID.getContent()); + if (FieldName.DOI.equals(eLocationID.getEIdType())) { + fields.put(FieldName.DOI, eLocationID.getContent()); } if ("pii".equals(eLocationID.getEIdType())) { fields.put("pii", eLocationID.getContent()); @@ -564,11 +565,11 @@ private void addElocationID(HashMap fields, ELocationID eLocatio private void addPubDate(HashMap fields, PubDate pubDate) { if (pubDate.getYear() == null) { //if year of the pubdate is null, the medlineDate shouldn't be null - fields.put("year", extractYear(pubDate.getMedlineDate())); + fields.put(FieldName.YEAR, extractYear(pubDate.getMedlineDate())); } else { - fields.put("year", pubDate.getYear()); + fields.put(FieldName.YEAR, pubDate.getYear()); if (pubDate.getMonth() != null) { - fields.put("month", pubDate.getMonth()); + fields.put(FieldName.MONTH, pubDate.getMonth()); } else if (pubDate.getSeason() != null) { fields.put("season", pubDate.getSeason()); } @@ -585,7 +586,7 @@ private void addAbstract(HashMap fields, Abstract abs) { } } } - fields.put("abstract", join(abstractText, " ")); + fields.put(FieldName.ABSTRACT, join(abstractText, " ")); } private void addPagination(HashMap fields, Pagination pagination) { @@ -593,15 +594,15 @@ private void addPagination(HashMap fields, Pagination pagination String endPage = ""; for (JAXBElement element : pagination.getContent()) { if ("MedlinePgn".equals(element.getName().getLocalPart())) { - putIfValueNotNull(fields, "pages", fixPageRange(element.getValue())); + putIfValueNotNull(fields, FieldName.PAGES, fixPageRange(element.getValue())); } else if ("StartPage".equals(element.getName().getLocalPart())) { //it could happen, that the article has only a start page startPage = element.getValue() + endPage; - putIfValueNotNull(fields, "pages", startPage); + putIfValueNotNull(fields, FieldName.PAGES, startPage); } else if ("EndPage".equals(element.getName().getLocalPart())) { endPage = element.getValue(); //but it should not happen, that a endpage appears without startpage - fields.put("pages", fixPageRange(startPage + "-" + endPage)); + fields.put(FieldName.PAGES, fixPageRange(startPage + "-" + endPage)); } } } @@ -629,7 +630,7 @@ private void handleAuthors(HashMap fields, AuthorList authors) { authorNames.add(authorName); } } - fields.put("author", join(authorNames, " and ")); + fields.put(FieldName.AUTHOR, join(authorNames, " and ")); } private static String join(List list, String string) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java index a73dfed8f79a..8ba449009ac4 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/MedlinePlainImporter.java @@ -157,21 +157,20 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { //store the fields in a map Map hashMap = new HashMap<>(); hashMap.put("PG", FieldName.PAGES); - hashMap.put("PL", "address"); + hashMap.put("PL", FieldName.ADDRESS); hashMap.put("PHST", "history"); hashMap.put("PST", "publication-status"); hashMap.put("VI", FieldName.VOLUME); - hashMap.put("LA", "language"); - hashMap.put("LA", "language"); + hashMap.put("LA", FieldName.LANGUAGE); hashMap.put("PUBM", "model"); hashMap.put("RN", "registry-number"); hashMap.put("NM", "substance-name"); hashMap.put("OCI", "copyright-owner"); hashMap.put("CN", "corporate"); hashMap.put("IP", FieldName.ISSUE); - hashMap.put("EN", "edition"); + hashMap.put("EN", FieldName.EDITION); hashMap.put("GS", "gene-symbol"); - hashMap.put("GN", "note"); + hashMap.put("GN", FieldName.NOTE); hashMap.put("GR", "grantno"); hashMap.put("SO", "source"); hashMap.put("NR", "number-of-references"); @@ -341,10 +340,10 @@ private void addTitles(Map hm, String lab, String val, String ty } } } else if ("BTI".equals(lab) || "CTI".equals(lab)) { - hm.put("booktitle", val); + hm.put(FieldName.BOOKTITLE, val); } else if ("JT".equals(lab)) { if ("inproceedings".equals(type)) { - hm.put("booktitle", val); + hm.put(FieldName.BOOKTITLE, val); } else { hm.put(FieldName.JOURNAL, val); } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java index 32689b7d4ce0..a924b30ddd5f 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/OvidImporter.java @@ -156,14 +156,14 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } else if ((matcher = OvidImporter.INCOLLECTION_PATTERN.matcher(content)).find()) { h.put(FieldName.EDITOR, matcher.group(1).replace(" (Ed)", "")); h.put(FieldName.YEAR, matcher.group(2)); - h.put("booktitle", matcher.group(3)); + h.put(FieldName.BOOKTITLE, matcher.group(3)); h.put(FieldName.PAGES, matcher.group(4)); - h.put("address", matcher.group(5)); + h.put(FieldName.ADDRESS, matcher.group(5)); h.put(FieldName.PUBLISHER, matcher.group(6)); } else if ((matcher = OvidImporter.BOOK_PATTERN.matcher(content)).find()) { h.put(FieldName.YEAR, matcher.group(1)); h.put(FieldName.PAGES, matcher.group(2)); - h.put("address", matcher.group(3)); + h.put(FieldName.ADDRESS, matcher.group(3)); h.put(FieldName.PUBLISHER, matcher.group(4)); } @@ -184,7 +184,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { h.put("entrytype", "inproceedings"); } } else if (fieldName.startsWith("Language")) { - h.put("language", content); + h.put(FieldName.LANGUAGE, content); } else if (fieldName.startsWith("Author Keywords")) { content = content.replace(";", ",").replace(" ", " "); h.put(FieldName.KEYWORDS, content); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java index 97ac6e5b8163..2a0e152668f4 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/PdfContentImporter.java @@ -458,13 +458,13 @@ public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { entry.setField(FieldName.TITLE, title); } if (conference != null) { - entry.setField("booktitle", conference); + entry.setField(FieldName.BOOKTITLE, conference); } if (DOI != null) { entry.setField(FieldName.DOI, DOI); } if (series != null) { - entry.setField("series", series); + entry.setField(FieldName.SERIES, series); } if (volume != null) { entry.setField(FieldName.VOLUME, volume); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java index 89ba9e6f3827..c616e6016cf4 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RepecNepImporter.java @@ -309,7 +309,7 @@ private void parseAuthors(BibEntry be, BufferedReader in) throws IOException { be.setField(FieldName.AUTHOR, String.join(" and ", authors)); } if (institutions.length() > 0) { - be.setField("institution", institutions.toString()); + be.setField(FieldName.INSTITUTION, institutions.toString()); } } diff --git a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java index 29c10eaffc26..1406ef3ac659 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/RisImporter.java @@ -147,9 +147,9 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } hm.put(FieldName.TITLE, hm.get(FieldName.TITLE).replaceAll("\\s+", " ")); // Normalize whitespaces } else if ("T2".equals(lab) || "BT".equals(lab)) { - hm.put("booktitle", val); + hm.put(FieldName.BOOKTITLE, val); } else if ("T3".equals(lab)) { - hm.put("series", val); + hm.put(FieldName.SERIES, val); } else if ("AU".equals(lab) || "A1".equals(lab)) { if ("".equals(author)) { author = val; @@ -164,7 +164,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } } else if ("JA".equals(lab) || "JF".equals(lab) || "JO".equals(lab)) { if ("inproceedings".equals(type)) { - hm.put("booktitle", val); + hm.put(FieldName.BOOKTITLE, val); } else { hm.put(FieldName.JOURNAL, val); } @@ -172,12 +172,12 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { startPage = val; } else if ("PB".equals(lab)) { if ("phdthesis".equals(type)) { - hm.put("school", val); + hm.put(FieldName.SCHOOL, val); } else { hm.put(FieldName.PUBLISHER, val); } } else if ("AD".equals(lab) || "CY".equals(lab)) { - hm.put("address", val); + hm.put(FieldName.ADDRESS, val); } else if ("EP".equals(lab)) { endPage = val; if (!endPage.isEmpty()) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java index e0db96ec5a77..cd349dbae324 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/SilverPlatterImporter.java @@ -160,7 +160,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } } else if ("AF".equals(f3)) { - h.put("school", frest.trim()); + h.put(FieldName.SCHOOL, frest.trim()); } else if ("DT".equals(f3)) { frest = frest.trim(); 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 98004464d4b4..048dc9bbc2b6 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java @@ -32,7 +32,7 @@ public class DoiCleanup implements CleanupJob { /** * Fields to check for DOIs. */ - private static final String[] FIELDS = {"note", FieldName.URL, "ee"}; + private static final String[] FIELDS = {FieldName.NOTE, FieldName.URL, "ee"}; @Override public List cleanup(BibEntry entry) { diff --git a/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java b/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java index 3a92ad2bfd2f..135893aaa6e3 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java +++ b/src/main/java/net/sf/jabref/logic/exporter/FieldFormatterCleanups.java @@ -38,7 +38,7 @@ public class FieldFormatterCleanups { List defaultFormatters = new ArrayList<>(); defaultFormatters.add(new FieldFormatterCleanup(FieldName.PAGES, new NormalizePagesFormatter())); defaultFormatters.add(new FieldFormatterCleanup(FieldName.MONTH, new NormalizeMonthFormatter())); - defaultFormatters.add(new FieldFormatterCleanup("booktitle", new OrdinalsToSuperscriptFormatter())); + defaultFormatters.add(new FieldFormatterCleanup(FieldName.BOOKTITLE, new OrdinalsToSuperscriptFormatter())); DEFAULT_SAVE_ACTIONS = new FieldFormatterCleanups(false, defaultFormatters); } diff --git a/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java index 6c60aa6d4bac..545c431bbdfe 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java @@ -166,27 +166,27 @@ public Document getDOMrepresentation() { addTableCell(result, row, getField(e, FieldName.MONTH)); addTableCell(result, row, getField(e, FieldName.PAGES)); addTableCell(result, row, getField(e, FieldName.YEAR)); - addTableCell(result, row, getField(e, "address")); - addTableCell(result, row, getField(e, "note")); + addTableCell(result, row, getField(e, FieldName.ADDRESS)); + addTableCell(result, row, getField(e, FieldName.NOTE)); addTableCell(result, row, getField(e, FieldName.URL)); - addTableCell(result, row, getField(e, "booktitle")); + addTableCell(result, row, getField(e, FieldName.BOOKTITLE)); addTableCell(result, row, getField(e, "chapter")); - addTableCell(result, row, getField(e, "edition")); - addTableCell(result, row, getField(e, "series")); + addTableCell(result, row, getField(e, FieldName.EDITION)); + addTableCell(result, row, getField(e, FieldName.SERIES)); addTableCell(result, row, getField(e, FieldName.EDITOR));//new AuthorLastFirst().format(getField(e, FieldName.EDITOR_FIELD))); addTableCell(result, row, getField(e, FieldName.PUBLISHER)); addTableCell(result, row, getField(e, "reporttype")); - addTableCell(result, row, getField(e, "howpublished")); - addTableCell(result, row, getField(e, "institution")); - addTableCell(result, row, getField(e, "organization")); - addTableCell(result, row, getField(e, "school")); + addTableCell(result, row, getField(e, FieldName.HOWPUBLISHED)); + addTableCell(result, row, getField(e, FieldName.INSTITUTION)); + addTableCell(result, row, getField(e, FieldName.ORGANIZATION)); + addTableCell(result, row, getField(e, FieldName.SCHOOL)); addTableCell(result, row, getField(e, "annote")); addTableCell(result, row, getField(e, "assignee")); addTableCell(result, row, getField(e, "day")); addTableCell(result, row, getField(e, "dayfiled")); addTableCell(result, row, getField(e, "monthfiled")); addTableCell(result, row, getField(e, "yearfiled")); - addTableCell(result, row, getField(e, "language")); + addTableCell(result, row, getField(e, FieldName.LANGUAGE)); addTableCell(result, row, getField(e, "nationality")); addTableCell(result, row, getField(e, "revision")); addTableCell(result, row, ""); diff --git a/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java index b8dbdc2abd6b..e075d095c578 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java @@ -162,31 +162,31 @@ public Document getDOMrepresentation() { row = result.createElement("table:table-row"); addTableCell(result, row, getField(e, BibEntry.KEY_FIELD)); addTableCell(result, row, new GetOpenOfficeType().format(e.getType())); - addTableCell(result, row, getField(e, "address")); + addTableCell(result, row, getField(e, FieldName.ADDRESS)); addTableCell(result, row, getField(e, "assignee")); addTableCell(result, row, getField(e, "annote")); addTableCell(result, row, getField(e, FieldName.AUTHOR));//new AuthorLastFirst().format(getField(e, FieldName.AUTHOR_FIELD))); - addTableCell(result, row, getField(e, "booktitle")); + addTableCell(result, row, getField(e, FieldName.BOOKTITLE)); addTableCell(result, row, getField(e, "chapter")); addTableCell(result, row, getField(e, "day")); addTableCell(result, row, getField(e, "dayfiled")); - addTableCell(result, row, getField(e, "edition")); + addTableCell(result, row, getField(e, FieldName.EDITION)); addTableCell(result, row, getField(e, FieldName.EDITOR));//new AuthorLastFirst().format(getField(e, FieldName.EDITOR_FIELD))); - addTableCell(result, row, getField(e, "howpublished")); - addTableCell(result, row, getField(e, "institution")); + addTableCell(result, row, getField(e, FieldName.HOWPUBLISHED)); + addTableCell(result, row, getField(e, FieldName.INSTITUTION)); addTableCell(result, row, getField(e, FieldName.JOURNAL)); - addTableCell(result, row, getField(e, "language")); + addTableCell(result, row, getField(e, FieldName.LANGUAGE)); addTableCell(result, row, getField(e, FieldName.MONTH)); addTableCell(result, row, getField(e, "monthfiled")); addTableCell(result, row, getField(e, "nationality")); - addTableCell(result, row, getField(e, "note")); + addTableCell(result, row, getField(e, FieldName.NOTE)); addTableCell(result, row, getField(e, FieldName.NUMBER)); - addTableCell(result, row, getField(e, "organization")); + addTableCell(result, row, getField(e, FieldName.ORGANIZATION)); addTableCell(result, row, getField(e, FieldName.PAGES)); addTableCell(result, row, getField(e, FieldName.PUBLISHER)); addTableCell(result, row, getField(e, "revision")); - addTableCell(result, row, getField(e, "school")); - addTableCell(result, row, getField(e, "series")); + addTableCell(result, row, getField(e, FieldName.SCHOOL)); + addTableCell(result, row, getField(e, FieldName.SERIES)); addTableCell(result, row, new RemoveWhitespace().format(new RemoveBrackets().format(getField(e, FieldName.TITLE)))); addTableCell(result, row, getField(e, "reporttype")); addTableCell(result, row, getField(e, FieldName.VOLUME)); diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 1a2920826f31..f27e7e96100f 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -63,7 +63,7 @@ private List checkBibtexEntry(BibEntry entry) { result.addAll(new FileChecker(bibDatabaseContext).check(entry)); result.addAll(new TypeChecker().check(entry)); result.addAll(new AbbreviationChecker(FieldName.JOURNAL).check(entry)); - result.addAll(new AbbreviationChecker("booktitle").check(entry)); + result.addAll(new AbbreviationChecker(FieldName.BOOKTITLE).check(entry)); result.addAll(new BibStringChecker().check(entry)); result.addAll(new HTMLCharacterChecker().check(entry)); result.addAll(new BooktitleChecker().check(entry)); @@ -100,7 +100,7 @@ private static class BooktitleChecker implements Checker { @Override public List check(BibEntry entry) { - String field = "booktitle"; + String field = FieldName.BOOKTITLE; Optional value = entry.getFieldOptional(field); if (!value.isPresent()) { return Collections.emptyList(); diff --git a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java index 88467cb77f43..507d422a68a4 100644 --- a/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java +++ b/src/main/java/net/sf/jabref/logic/labelpattern/LabelPatternUtil.java @@ -310,7 +310,7 @@ private static String generateInstitutionKey(String content) { if (k.matches("^[Tt][Ee][Cc][Hh].*")) { // Starts with "tech" case and locale independent isTechnology = true; } - if ("school".equalsIgnoreCase(k)) { + if (FieldName.SCHOOL.equalsIgnoreCase(k)) { isSchool = true; } if (k.matches("^[Dd][EeIi][Pp].*") || k.matches("^[Ll][Aa][Bb].*")) { // Starts with "dep"/"dip"/"lab", case and locale independent @@ -347,7 +347,7 @@ private static String generateInstitutionKey(String content) { StringBuilder schoolSB = new StringBuilder(); StringBuilder departmentSB = new StringBuilder(); for (String k : part) { - if (!k.matches("^[Dd][EeIi][Pp].*") && !"school".equalsIgnoreCase(k) + if (!k.matches("^[Dd][EeIi][Pp].*") && !FieldName.SCHOOL.equalsIgnoreCase(k) && !"faculty".equalsIgnoreCase(k) && !(k.replaceAll(STARTING_CAPITAL_PATTERN, "").isEmpty())) { if (isSchool) { diff --git a/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java b/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java index abf9d73c0b97..df6e3748da99 100644 --- a/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java +++ b/src/main/java/net/sf/jabref/logic/mods/MODSEntry.java @@ -131,7 +131,7 @@ private void populateFromBibtex(BibEntry bibtex) { if ("article".equals(bibtex.getType()) || "inproceedings".equals(bibtex.getType())) { host = new MODSEntry(); host.entryType = "relatedItem"; - host.title = bibtex.getField("booktitle"); + host.title = bibtex.getField(FieldName.BOOKTITLE); host.publisher = bibtex.getField(FieldName.PUBLISHER); host.number = bibtex.getField(FieldName.NUMBER); if (bibtex.hasField(FieldName.VOLUME)) { diff --git a/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java b/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java index acd7292073f8..c7a2257a2247 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java +++ b/src/main/java/net/sf/jabref/logic/msbib/BibTeXConverter.java @@ -38,9 +38,9 @@ public static BibEntry convert(MSBibEntry entry) { } // Value must be converted - if (fieldValues.containsKey("language")) { - int lcid = Integer.valueOf(fieldValues.get("language")); - fieldValues.put("language", MSBibMapping.getLanguage(lcid)); + if (fieldValues.containsKey(FieldName.LANGUAGE)) { + int lcid = Integer.valueOf(fieldValues.get(FieldName.LANGUAGE)); + fieldValues.put(FieldName.LANGUAGE, MSBibMapping.getLanguage(lcid)); } addAuthor(fieldValues, FieldName.AUTHOR, entry.authors); @@ -66,11 +66,11 @@ public static BibEntry convert(MSBibEntry entry) { parseStandardNumber(entry.standardNumber, fieldValues); if (entry.address != null) { - fieldValues.put("address", entry.address); + fieldValues.put(FieldName.ADDRESS, entry.address); } // TODO: ConferenceName is saved as booktitle when converting from MSBIB to BibTeX if (entry.conferenceName != null) { - fieldValues.put("organization", entry.conferenceName); + fieldValues.put(FieldName.ORGANIZATION, entry.conferenceName); } if (entry.dateAccessed != null) { diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java index 95506884b93c..f7e9d8089446 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibConverter.java @@ -32,8 +32,8 @@ public static MSBibEntry convert(BibEntry entry) { } // Duplicate: also added as BookTitle - if (entry.hasField("booktitle")) { - result.conferenceName = entry.getField("booktitle"); + if (entry.hasField(FieldName.BOOKTITLE)) { + result.conferenceName = entry.getField(FieldName.BOOKTITLE); } if (entry.hasField(FieldName.PAGES)) { @@ -55,8 +55,8 @@ public static MSBibEntry convert(BibEntry entry) { } // Value must be converted - if (entry.hasField("language")) { - result.fields.put("LCID", String.valueOf(MSBibMapping.getLCID(entry.getField("language")))); + if (entry.hasField(FieldName.LANGUAGE)) { + result.fields.put("LCID", String.valueOf(MSBibMapping.getLCID(entry.getField(FieldName.LANGUAGE)))); } result.standardNumber = ""; @@ -79,12 +79,12 @@ public static MSBibEntry convert(BibEntry entry) { result.standardNumber = null; } - if (entry.hasField("address")) { - result.address = entry.getField("address"); + if (entry.hasField(FieldName.ADDRESS)) { + result.address = entry.getField(FieldName.ADDRESS); } - if (entry.hasField("type")) { - result.thesisType = entry.getField("type"); + if (entry.hasField(FieldName.TYPE)) { + result.thesisType = entry.getField(FieldName.TYPE); } else { if ("techreport".equalsIgnoreCase(entry.getType())) { result.thesisType = "Tech. rep."; diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java index 89a78d357783..eff6257ee4ef 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java @@ -20,27 +20,27 @@ public class MSBibMapping { bibtexToMSBib.put(FieldName.TITLE, "Title"); bibtexToMSBib.put(FieldName.YEAR, "Year"); bibtexToMSBib.put(FieldName.MONTH, "Month"); - bibtexToMSBib.put("note", "Comments"); + bibtexToMSBib.put(FieldName.NOTE, "Comments"); bibtexToMSBib.put(FieldName.VOLUME, "Volume"); - bibtexToMSBib.put("language", "LCID"); - bibtexToMSBib.put("edition", "Edition"); + bibtexToMSBib.put(FieldName.LANGUAGE, "LCID"); + bibtexToMSBib.put(FieldName.EDITION, "Edition"); bibtexToMSBib.put(FieldName.PUBLISHER, "Publisher"); - bibtexToMSBib.put("booktitle", "BookTitle"); - //bibtexToMSBib.put("booktitle", "ConferenceName"); + bibtexToMSBib.put(FieldName.BOOKTITLE, "BookTitle"); + //bibtexToMSBib.put(FieldName.BOOKTITLE, "ConferenceName"); //bibtexToMSBib.put(FieldName.PAGES, "Pages"); bibtexToMSBib.put("chapter", "ChapterNumber"); bibtexToMSBib.put(FieldName.JOURNAL, "JournalName"); bibtexToMSBib.put(FieldName.NUMBER, "Issue"); - bibtexToMSBib.put("school", "Department"); - bibtexToMSBib.put("institution", "Institution"); + bibtexToMSBib.put(FieldName.SCHOOL, "Department"); + bibtexToMSBib.put(FieldName.INSTITUTION, "Institution"); bibtexToMSBib.put(FieldName.DOI, "DOI"); bibtexToMSBib.put(FieldName.URL, "URL"); // BibTeX/Biblatex only fields - bibtexToMSBib.put("series", BIBTEX_PREFIX + "Series"); + bibtexToMSBib.put(FieldName.SERIES, BIBTEX_PREFIX + "Series"); bibtexToMSBib.put(FieldName.ABSTRACT, BIBTEX_PREFIX + "Abstract"); bibtexToMSBib.put(FieldName.KEYWORDS, BIBTEX_PREFIX + "KeyWords"); bibtexToMSBib.put(FieldName.CROSSREF, BIBTEX_PREFIX + "CrossRef"); - bibtexToMSBib.put("howpublished", BIBTEX_PREFIX + "HowPublished"); + bibtexToMSBib.put(FieldName.HOWPUBLISHED, BIBTEX_PREFIX + "HowPublished"); bibtexToMSBib.put("affiliation", BIBTEX_PREFIX + "Affiliation"); bibtexToMSBib.put("contents", BIBTEX_PREFIX + "Contents"); bibtexToMSBib.put("copyright", BIBTEX_PREFIX + "Copyright"); @@ -60,7 +60,7 @@ public class MSBibMapping { bibtexToMSBib.put(MSBIB_PREFIX + "distributor", "Distributor"); bibtexToMSBib.put(MSBIB_PREFIX + "broadcaster", "Broadcaster"); bibtexToMSBib.put(MSBIB_PREFIX + "station", "Station"); - bibtexToMSBib.put(MSBIB_PREFIX + "type", "Type"); + bibtexToMSBib.put(MSBIB_PREFIX + FieldName.TYPE, "Type"); bibtexToMSBib.put(MSBIB_PREFIX + "patentnumber", "PatentNumber"); bibtexToMSBib.put(MSBIB_PREFIX + "court", "Court"); bibtexToMSBib.put(MSBIB_PREFIX + "reporter", "Reporter"); diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java index e5bb44522eb6..08e081feb486 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPSchemaBibtex.java @@ -55,7 +55,7 @@ public class XMPSchemaBibtex extends XMPSchema { static { XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add(FieldName.ABSTRACT); - XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add("note"); + XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add(FieldName.NOTE); XMPSchemaBibtex.PRESERVE_WHITE_SPACE.add(FieldName.REVIEW); } diff --git a/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java index cd428e972c46..87a04ed9c290 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java @@ -29,14 +29,14 @@ public class BibLatexEntryTypes { public static final BibLatexEntryType ARTICLE = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", FieldName.EDITOR, "series", FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.PAGES, - "note", FieldName.ISSN, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + Arrays.asList("subtitle", FieldName.EDITOR, FieldName.SERIES, FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.PAGES, + FieldName.NOTE, FieldName.ISSN, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.JOURNALTITLE, "year/date"); addAllOptional("translator", "annotator", "commentator", "subtitle", "titleaddon", FieldName.EDITOR, "editora", - "editorb", "editorc", "journalsubtitle", "issuetitle", "issuesubtitle", "language", "origlanguage", - "series", FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.MONTH, FieldName.PAGES, "version", "note", FieldName.ISSN, + "editorb", "editorc", "journalsubtitle", "issuetitle", "issuesubtitle", FieldName.LANGUAGE, "origlanguage", + FieldName.SERIES, FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.MONTH, FieldName.PAGES, "version", FieldName.NOTE, FieldName.ISSN, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -55,7 +55,7 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", - "mainsubtitle", "maintitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, + "mainsubtitle", "maintitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); @@ -63,8 +63,8 @@ public List getPrimaryOptionalFields() { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "language", "origlanguage", FieldName.VOLUME, "part", "edition", "volumes", "series", - FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + "maintitleaddon", FieldName.LANGUAGE, "origlanguage", FieldName.VOLUME, "part", FieldName.EDITION, "volumes", FieldName.SERIES, + FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -82,14 +82,14 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MVBOOK = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList(FieldName.EDITOR, "subtitle", "titleaddon", "edition", FieldName.PUBLISHER, FieldName.ISBN, "pagetotal", + .unmodifiableList(Arrays.asList(FieldName.EDITOR, "subtitle", "titleaddon", FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", - "introduction", "foreword", "afterword", "subtitle", "titleaddon", "language", "origlanguage", - "edition", "volumes", "series", FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, "pagetotal", + "introduction", "foreword", "afterword", "subtitle", "titleaddon", FieldName.LANGUAGE, "origlanguage", + FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -108,16 +108,16 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections.unmodifiableList(Arrays .asList("bookauthor", FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, + "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", "year/date"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, "year/date"); addAllOptional("bookauthor", FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", - "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", "language", "origlanguage", - FieldName.VOLUME, "part", "edition", "volumes", "series", FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, + "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.LANGUAGE, "origlanguage", + FieldName.VOLUME, "part", FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -184,12 +184,12 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType BOOKLET = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "howpublished", "chapter", + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { addAllRequired("author/editor", FieldName.TITLE, "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "howpublished", "type", "note", "location", "chapter", + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.TYPE, FieldName.NOTE, "location", "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -209,7 +209,7 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", "maintitle", - "mainsubtitle", "maintitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, + "mainsubtitle", "maintitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); @@ -217,7 +217,7 @@ public List getPrimaryOptionalFields() { addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); addAllOptional("editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", - "language", "origlanguage", FieldName.VOLUME, "part", "edition", "volumes", "series", FieldName.NUMBER, "note", + FieldName.LANGUAGE, "origlanguage", FieldName.VOLUME, "part", FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -236,14 +236,14 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MVCOLLECTION = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", "edition", FieldName.PUBLISHER, FieldName.ISBN, + .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); addAllOptional("editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", - "foreword", "afterword", "subtitle", "titleaddon", "language", "origlanguage", "edition", "volumes", "series", FieldName.NUMBER, "note", + "foreword", "afterword", "subtitle", "titleaddon", FieldName.LANGUAGE, "origlanguage", FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -263,16 +263,16 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections.unmodifiableList( Arrays.asList("translator", "subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, "edition", FieldName.PUBLISHER, FieldName.ISBN, + "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", "year/date"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, "year/date"); addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", - "booksubtitle", "booktitleaddon", "language", "origlanguage", FieldName.VOLUME, "part", "edition", - "volumes", "series", FieldName.NUMBER, "note", FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, + "booksubtitle", "booktitleaddon", FieldName.LANGUAGE, "origlanguage", FieldName.VOLUME, "part", FieldName.EDITION, + "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -314,14 +314,14 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MANUAL = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "edition", FieldName.PUBLISHER, FieldName.ISBN, + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { addAllRequired("author/editor", FieldName.TITLE, "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "edition", "type", "series", FieldName.NUMBER, "version", - "note", "organization", FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.EDITION, FieldName.TYPE, FieldName.SERIES, FieldName.NUMBER, "version", + FieldName.NOTE, FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -339,14 +339,14 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MISC = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "howpublished", "location", + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, "location", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { addAllRequired("author/editor", FieldName.TITLE, "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "howpublished", "type", "version", "note", - "organization", "location", FieldName.MONTH, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.TYPE, "version", FieldName.NOTE, + FieldName.ORGANIZATION, "location", FieldName.MONTH, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -364,12 +364,12 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType ONLINE = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", "note", "organization", "urldate")); + Arrays.asList("subtitle", "titleaddon", FieldName.NOTE, FieldName.ORGANIZATION, "urldate")); { addAllRequired("author/editor", FieldName.TITLE, "year/date", FieldName.URL); - addAllOptional("subtitle", "titleaddon", "language", "version", "note", "organization", FieldName.MONTH, "addendum", "pubstate", "urldate"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, "version", FieldName.NOTE, FieldName.ORGANIZATION, FieldName.MONTH, "addendum", "pubstate", "urldate"); } @Override @@ -391,7 +391,7 @@ public List getPrimaryOptionalFields() { { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.NUMBER, "year/date"); - addAllOptional("holder", "subtitle", "titleaddon", "type", "version", "location", "note", FieldName.MONTH, + addAllOptional("holder", "subtitle", "titleaddon", FieldName.TYPE, "version", "location", FieldName.NOTE, FieldName.MONTH, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -415,8 +415,8 @@ public List getPrimaryOptionalFields() { { addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); - addAllOptional("editora", "editorb", "editorc", "subtitle", "issuetitle", "issuesubtitle", "language", - "series", FieldName.VOLUME, FieldName.NUMBER, FieldName.ISSUE, FieldName.MONTH, "note", FieldName.ISSN, "addendum", "pubstate", + addAllOptional("editora", "editorb", "editorc", "subtitle", "issuetitle", "issuesubtitle", FieldName.LANGUAGE, + FieldName.SERIES, FieldName.VOLUME, FieldName.NUMBER, FieldName.ISSUE, FieldName.MONTH, FieldName.NOTE, FieldName.ISSN, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -466,8 +466,8 @@ public List getPrimaryOptionalFields() { { addAllRequired(FieldName.TITLE, "year/date"); addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "eventtitle", - "eventtitleaddon", "eventdate", "venue", "language", FieldName.VOLUME, "part", "volumes", "series", FieldName.NUMBER, "note", - "organization", FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.YEAR, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", + "eventtitleaddon", "eventdate", "venue", FieldName.LANGUAGE, FieldName.VOLUME, "part", "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, + FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.YEAR, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -493,8 +493,8 @@ public List getPrimaryOptionalFields() { { addAllRequired(FieldName.TITLE, "year/date"); addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "eventtitle", - "eventtitleaddon", "eventdate", "venue", "language", "volumes", "series", FieldName.NUMBER, "note", - "organization", FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, "pagetotal", + "eventtitleaddon", "eventdate", "venue", FieldName.LANGUAGE, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, + FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -518,10 +518,10 @@ public List getPrimaryOptionalFields() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", "year/date"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, "year/date"); addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", - "booktitleaddon", "eventtitle", "eventtitleaddon", "eventdate", "venue", "language", FieldName.VOLUME, "part", "volumes", - "series", FieldName.NUMBER, "note", "organization", FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, + "booktitleaddon", "eventtitle", "eventtitleaddon", "eventdate", "venue", FieldName.LANGUAGE, FieldName.VOLUME, "part", "volumes", + FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, "chapter", FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -617,8 +617,8 @@ public List getPrimaryOptionalFields() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "type", "institution", "year/date"); - addAllOptional("subtitle", "titleaddon", "language", FieldName.NUMBER, "version", "note", "location", FieldName.MONTH, + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.TYPE, FieldName.INSTITUTION, "year/date"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NUMBER, "version", FieldName.NOTE, "location", FieldName.MONTH, "isrn", "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -653,8 +653,8 @@ public String getName() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "type", "institution", "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "note", "location", FieldName.MONTH, FieldName.ISBN, "chapter", + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.TYPE, FieldName.INSTITUTION, "year/date"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, "location", FieldName.MONTH, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -673,12 +673,12 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType UNPUBLISHED = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", "howpublished", "pubstate", FieldName.URL, "urldate")); + Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, "pubstate", FieldName.URL, "urldate")); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); - addAllOptional("subtitle", "titleaddon", "language", "howpublished", "note", "location", FieldName.MONTH, + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.NOTE, "location", FieldName.MONTH, "addendum", "pubstate", FieldName.URL, "urldate"); } @@ -746,14 +746,14 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MASTERSTHESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "type", "chapter", FieldName.PAGES, + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, "chapter", FieldName.PAGES, "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - // Treated as alias of "THESIS", except "type" field is optional - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", "year/date"); - addAllOptional("type", "subtitle", "titleaddon", "language", "note", "location", FieldName.MONTH, FieldName.ISBN, "chapter", + // Treated as alias of "THESIS", except FieldName.TYPE field is optional + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.INSTITUTION, "year/date"); + addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, "location", FieldName.MONTH, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -772,14 +772,14 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType PHDTHESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "type", "chapter", FieldName.PAGES, + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, "chapter", FieldName.PAGES, "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - // Treated as alias of "THESIS", except "type" field is optional - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", "year/date"); - addAllOptional("type", "subtitle", "titleaddon", "language", "note", "location", FieldName.MONTH, FieldName.ISBN, "chapter", + // Treated as alias of "THESIS", except FieldName.TYPE field is optional + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.INSTITUTION, "year/date"); + addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, "location", FieldName.MONTH, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } @@ -798,14 +798,14 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType TECHREPORT = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", "type", FieldName.NUMBER, "isrn", "chapter", FieldName.PAGES, + Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, FieldName.NUMBER, "isrn", "chapter", FieldName.PAGES, "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); { - // Treated as alias of "REPORT", except "type" field is optional - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", "year/date"); - addAllOptional("type", "subtitle", "titleaddon", "language", FieldName.NUMBER, "version", "note", "location", FieldName.MONTH, + // Treated as alias of "REPORT", except FieldName.TYPE field is optional + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.INSTITUTION, "year/date"); + addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NUMBER, "version", FieldName.NOTE, "location", FieldName.MONTH, "isrn", "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); } diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java index 0c906913a551..313c54812170 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java @@ -21,7 +21,7 @@ public class BibtexEntryTypes { { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.JOURNAL, FieldName.YEAR); - addAllOptional(FieldName.VOLUME, FieldName.NUMBER, FieldName.PAGES, FieldName.MONTH, "note"); + addAllOptional(FieldName.VOLUME, FieldName.NUMBER, FieldName.PAGES, FieldName.MONTH, FieldName.NOTE); } @Override @@ -40,7 +40,7 @@ public String getName() { { addAllRequired(FieldName.TITLE, FieldName.PUBLISHER, FieldName.YEAR, "author/editor"); - addAllOptional(FieldName.VOLUME, FieldName.NUMBER, "series", "address", "edition", FieldName.MONTH, "note"); + addAllOptional(FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.ADDRESS, FieldName.EDITION, FieldName.MONTH, FieldName.NOTE); } @Override @@ -59,7 +59,7 @@ public String getName() { { addAllRequired(FieldName.TITLE); - addAllOptional(FieldName.AUTHOR, "howpublished", "address", FieldName.MONTH, FieldName.YEAR, "note"); + addAllOptional(FieldName.AUTHOR, FieldName.HOWPUBLISHED, FieldName.ADDRESS, FieldName.MONTH, FieldName.YEAR, FieldName.NOTE); } @Override @@ -77,9 +77,9 @@ public String getName() { public static final EntryType CONFERENCE = new BibtexEntryType() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", FieldName.YEAR); - addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", FieldName.PAGES, "address", FieldName.MONTH, "organization", - FieldName.PUBLISHER, "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, FieldName.YEAR); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.PAGES, FieldName.ADDRESS, FieldName.MONTH, FieldName.ORGANIZATION, + FieldName.PUBLISHER, FieldName.NOTE); } @Override @@ -98,7 +98,7 @@ public String getName() { { addAllRequired("chapter/pages", FieldName.TITLE, FieldName.PUBLISHER, FieldName.YEAR, "author/editor"); - addAllOptional(FieldName.VOLUME, FieldName.NUMBER, "series", "type", "address", "edition", FieldName.MONTH, "note"); + addAllOptional(FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.TYPE, FieldName.ADDRESS, FieldName.EDITION, FieldName.MONTH, FieldName.NOTE); } @Override @@ -115,9 +115,9 @@ public String getName() { public static final EntryType INCOLLECTION = new BibtexEntryType() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", FieldName.PUBLISHER, FieldName.YEAR); - addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", "type", "chapter", FieldName.PAGES, "address", "edition", - FieldName.MONTH, "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, FieldName.PUBLISHER, FieldName.YEAR); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.TYPE, "chapter", FieldName.PAGES, FieldName.ADDRESS, FieldName.EDITION, + FieldName.MONTH, FieldName.NOTE); } @Override @@ -135,9 +135,9 @@ public String getName() { public static final EntryType INPROCEEDINGS = new BibtexEntryType() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "booktitle", FieldName.YEAR); - addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", FieldName.PAGES, "address", FieldName.MONTH, "organization", - FieldName.PUBLISHER, "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, FieldName.YEAR); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.PAGES, FieldName.ADDRESS, FieldName.MONTH, FieldName.ORGANIZATION, + FieldName.PUBLISHER, FieldName.NOTE); } @Override @@ -155,7 +155,7 @@ public String getName() { { addAllRequired(FieldName.TITLE); - addAllOptional(FieldName.AUTHOR, "organization", "address", "edition", FieldName.MONTH, FieldName.YEAR, "note"); + addAllOptional(FieldName.AUTHOR, FieldName.ORGANIZATION, FieldName.ADDRESS, FieldName.EDITION, FieldName.MONTH, FieldName.YEAR, FieldName.NOTE); } @Override @@ -173,8 +173,8 @@ public String getName() { public static final EntryType MASTERSTHESIS = new BibtexEntryType() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "school", FieldName.YEAR); - addAllOptional("type", "address", FieldName.MONTH, "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.SCHOOL, FieldName.YEAR); + addAllOptional(FieldName.TYPE, FieldName.ADDRESS, FieldName.MONTH, FieldName.NOTE); } @Override @@ -192,7 +192,7 @@ public String getName() { public static final EntryType MISC = new BibtexEntryType() { { - addAllOptional(FieldName.AUTHOR, FieldName.TITLE, "howpublished", FieldName.MONTH, FieldName.YEAR, "note"); + addAllOptional(FieldName.AUTHOR, FieldName.TITLE, FieldName.HOWPUBLISHED, FieldName.MONTH, FieldName.YEAR, FieldName.NOTE); } @Override @@ -210,8 +210,8 @@ public String getName() { public static final EntryType PHDTHESIS = new BibtexEntryType() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "school", FieldName.YEAR); - addAllOptional("type", "address", FieldName.MONTH, "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.SCHOOL, FieldName.YEAR); + addAllOptional(FieldName.TYPE, FieldName.ADDRESS, FieldName.MONTH, FieldName.NOTE); } @Override @@ -230,8 +230,8 @@ public String getName() { { addAllRequired(FieldName.TITLE, FieldName.YEAR); - addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, "series", "address", FieldName.PUBLISHER, "note", FieldName.MONTH, - "organization"); + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.ADDRESS, FieldName.PUBLISHER, FieldName.NOTE, FieldName.MONTH, + FieldName.ORGANIZATION); } @Override @@ -249,8 +249,8 @@ public String getName() { public static final EntryType TECHREPORT = new BibtexEntryType() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "institution", FieldName.YEAR); - addAllOptional("type", FieldName.NUMBER, "address", FieldName.MONTH, "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.INSTITUTION, FieldName.YEAR); + addAllOptional(FieldName.TYPE, FieldName.NUMBER, FieldName.ADDRESS, FieldName.MONTH, FieldName.NOTE); } @Override @@ -268,7 +268,7 @@ public String getName() { public static final EntryType UNPUBLISHED = new BibtexEntryType() { { - addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "note"); + addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.NOTE); addAllOptional(FieldName.MONTH, FieldName.YEAR); } diff --git a/src/main/java/net/sf/jabref/model/entry/EntryConverter.java b/src/main/java/net/sf/jabref/model/entry/EntryConverter.java index ad48e6e1d32c..67bae56b1f4f 100644 --- a/src/main/java/net/sf/jabref/model/entry/EntryConverter.java +++ b/src/main/java/net/sf/jabref/model/entry/EntryConverter.java @@ -17,14 +17,14 @@ public class EntryConverter { static { EntryConverter.FIELD_ALIASES_TEX_TO_LTX = new HashMap<>(); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("address", "location"); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.ADDRESS, "location"); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("annote", "annotation"); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("archiveprefix", "eprinttype"); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.JOURNAL, FieldName.JOURNALTITLE); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("key", "sortkey"); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("pdf", FieldName.FILE); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("primaryclass", "eprintclass"); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("school", "institution"); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.SCHOOL, FieldName.INSTITUTION); // inverse map EntryConverter.FIELD_ALIASES_LTX_TO_TEX = EntryConverter.FIELD_ALIASES_TEX_TO_LTX.entrySet() diff --git a/src/main/java/net/sf/jabref/model/entry/FieldName.java b/src/main/java/net/sf/jabref/model/entry/FieldName.java index 5de9895789d4..0f74b25663f5 100644 --- a/src/main/java/net/sf/jabref/model/entry/FieldName.java +++ b/src/main/java/net/sf/jabref/model/entry/FieldName.java @@ -4,28 +4,37 @@ public class FieldName { public static final String ABSTRACT = "abstract"; + public static final String ADDRESS = "address"; public static final String AUTHOR = "author"; + public static final String BOOKTITLE = "booktitle"; public static final String CROSSREF = "crossref"; public static final String DATE = "date"; public static final String DOI = "doi"; + public static final String EDITION = "edition"; public static final String EDITOR = "editor"; public static final String FILE = "file"; public static final String FOLDER = "folder"; + public static final String HOWPUBLISHED = "howpublished"; + public static final String INSTITUTION = "institution"; public static final String ISBN = "isbn"; public static final String ISSN = "issn"; public static final String ISSUE = "issue"; public static final String JOURNAL = "journal"; public static final String JOURNALTITLE = "journaltitle"; public static final String KEYWORDS = "keywords"; + public static final String LANGUAGE = "language"; public static final String MONTH = "month"; + public static final String NOTE = "note"; public static final String NUMBER = "number"; + public static final String ORGANIZATION = "organization"; public static final String PAGES = "pages"; public static final String PUBLISHER = "publisher"; public static final String REVIEW = "review"; + public static final String SCHOOL = "school"; + public static final String SERIES = "series"; public static final String TITLE = "title"; + public static final String TYPE = "type"; public static final String URL = "url"; public static final String VOLUME = "volume"; public static final String YEAR = "year"; - - } diff --git a/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java index fe0816f5b17e..ab8e809dabe8 100644 --- a/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java @@ -20,8 +20,8 @@ public class IEEETranEntryTypes { public static final EntryType ELECTRONIC = new BibtexEntryType() { { - addAllOptional(FieldName.AUTHOR, FieldName.MONTH, FieldName.YEAR, FieldName.TITLE, "language", "howpublished", "organization", "address", - "note", FieldName.URL); + addAllOptional(FieldName.AUTHOR, FieldName.MONTH, FieldName.YEAR, FieldName.TITLE, FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.ORGANIZATION, FieldName.ADDRESS, + FieldName.NOTE, FieldName.URL); } @@ -59,7 +59,7 @@ public String getName() { { addAllRequired(FieldName.TITLE, FieldName.YEAR); - addAllOptional(FieldName.EDITOR, "language", "series", FieldName.VOLUME, FieldName.NUMBER, "organization", FieldName.MONTH, "note", FieldName.URL); + addAllOptional(FieldName.EDITOR, FieldName.LANGUAGE, FieldName.SERIES, FieldName.VOLUME, FieldName.NUMBER, FieldName.ORGANIZATION, FieldName.MONTH, FieldName.NOTE, FieldName.URL); } @Override @@ -78,8 +78,8 @@ public String getName() { { addAllRequired("nationality", FieldName.NUMBER, "year/yearfiled"); - addAllOptional(FieldName.AUTHOR, FieldName.TITLE, "language", "assignee", "address", "type", FieldName.NUMBER, "day", "dayfiled", - FieldName.MONTH, "monthfiled", "note", FieldName.URL); + addAllOptional(FieldName.AUTHOR, FieldName.TITLE, FieldName.LANGUAGE, "assignee", FieldName.ADDRESS, FieldName.TYPE, FieldName.NUMBER, "day", "dayfiled", + FieldName.MONTH, "monthfiled", FieldName.NOTE, FieldName.URL); } @Override @@ -98,8 +98,8 @@ public String getName() { { addAllRequired(FieldName.TITLE, "organization/institution"); - addAllOptional(FieldName.AUTHOR, "language", "howpublished", "type", FieldName.NUMBER, "revision", "address", FieldName.MONTH, - FieldName.YEAR, "note", FieldName.URL); + addAllOptional(FieldName.AUTHOR, FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.TYPE, FieldName.NUMBER, "revision", FieldName.ADDRESS, FieldName.MONTH, + FieldName.YEAR, FieldName.NOTE, FieldName.URL); } @Override diff --git a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index 4f8f4614e074..35cb282cac8c 100644 --- a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -88,21 +88,21 @@ private InternalBibtexFields(boolean serializeSpecialFields) { // FIRST: all standard fields // These are the fields that BibTex might want to treat, so these // must conform to BibTex rules. - add(new BibtexSingleField("address", true, BibtexSingleField.SMALL_W)); + add(new BibtexSingleField(FieldName.ADDRESS, true, BibtexSingleField.SMALL_W)); // An annotation. It is not used by the standard bibliography styles, // but may be used by others that produce an annotated bibliography. // http://www.ecst.csuchico.edu/~jacobsd/bib/formats/bibtex.html add(new BibtexSingleField("annote", true, BibtexSingleField.LARGE_W)); add(new BibtexSingleField(FieldName.AUTHOR, true, BibtexSingleField.MEDIUM_W, 280)); - add(new BibtexSingleField("booktitle", true, 175)); + add(new BibtexSingleField(FieldName.BOOKTITLE, true, 175)); add(new BibtexSingleField("chapter", true, BibtexSingleField.SMALL_W)); dummy = new BibtexSingleField(FieldName.CROSSREF, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.CROSSREF)); add(dummy); - add(new BibtexSingleField("edition", true, BibtexSingleField.SMALL_W)); + add(new BibtexSingleField(FieldName.EDITION, true, BibtexSingleField.SMALL_W)); add(new BibtexSingleField(FieldName.EDITOR, true, BibtexSingleField.MEDIUM_W, 280)); - add(new BibtexSingleField("howpublished", true, BibtexSingleField.MEDIUM_W)); - add(new BibtexSingleField("institution", true, BibtexSingleField.MEDIUM_W)); + add(new BibtexSingleField(FieldName.HOWPUBLISHED, true, BibtexSingleField.MEDIUM_W)); + add(new BibtexSingleField(FieldName.INSTITUTION, true, BibtexSingleField.MEDIUM_W)); dummy = new BibtexSingleField(FieldName.JOURNAL, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.JOURNAL_NAME)); @@ -115,18 +115,18 @@ private InternalBibtexFields(boolean serializeSpecialFields) { dummy = new BibtexSingleField(FieldName.MONTH, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.MONTH)); add(dummy); - add(new BibtexSingleField("note", true, BibtexSingleField.MEDIUM_W)); + add(new BibtexSingleField(FieldName.NOTE, true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField(FieldName.NUMBER, true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); - add(new BibtexSingleField("organization", true, BibtexSingleField.MEDIUM_W)); + add(new BibtexSingleField(FieldName.ORGANIZATION, true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField(FieldName.PAGES, true, BibtexSingleField.SMALL_W)); add(new BibtexSingleField(FieldName.PUBLISHER, true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField("school", true, BibtexSingleField.MEDIUM_W)); - add(new BibtexSingleField("series", true, BibtexSingleField.SMALL_W)); + add(new BibtexSingleField(FieldName.SERIES, true, BibtexSingleField.SMALL_W)); add(new BibtexSingleField(FieldName.TITLE, true, 400)); - dummy = new BibtexSingleField("type", true, BibtexSingleField.SMALL_W); + dummy = new BibtexSingleField(FieldName.TYPE, true, BibtexSingleField.SMALL_W); dummy.getExtras().add(FieldProperties.TYPE); add(dummy); - add(new BibtexSingleField("language", true, BibtexSingleField.SMALL_W)); + add(new BibtexSingleField(FieldName.LANGUAGE, true, BibtexSingleField.SMALL_W)); add(new BibtexSingleField(FieldName.VOLUME, true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); add(new BibtexSingleField(FieldName.YEAR, true, BibtexSingleField.SMALL_W, 60).setNumeric(true)); From 7ff7cbe88569c6e7d6f3c7daef364992437378d5 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Fri, 22 Jul 2016 11:36:00 +0200 Subject: [PATCH 261/268] Set user agent to fix 403 status error --- src/test/java/net/sf/jabref/gui/help/HelpFileTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java b/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java index 62f4beda4c1f..0859551bb592 100644 --- a/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java +++ b/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java @@ -15,6 +15,7 @@ public void referToValidPage() throws IOException { for (HelpFile help : HelpFile.values()) { URL url = new URL(jabrefHelp + help.getPageName()); HttpURLConnection http = (HttpURLConnection) url.openConnection(); + http.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64)"); assertEquals(200, http.getResponseCode()); } } From c6aa7dac3c76cbbdd5142cb43e084ea32e89ec47 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 22 Jul 2016 18:15:39 +0200 Subject: [PATCH 262/268] [WIP] Create new fetcher infrastructure (#1594) * Introduce new Fetcher interfaces * Refactor arXiv fulltext fetcher * Add query based arXiv fetcher * Reformat code * Add a few tests for the arxiv parser * Make new arXiv fetcher available * Fix small problems related to files * Fix tests * Rename interface methods * Add changelog entry * Mark old EntryFetcher interface as deprecated * Move fetcher to importer \ fetcher * Move HelpFile from gui.help to logic.help * Rename fetchers * Rename FulltextFinder * Optimize imports * Fix failing test * Ignore failing test --- CHANGELOG.md | 1 + .../jabref/external/FindFullTextAction.java | 4 +- .../sf/jabref/gui/ContentSelectorDialog2.java | 2 +- .../sf/jabref/gui/GenFieldsCustomizer.java | 2 +- .../sf/jabref/gui/ImportInspectionDialog.java | 4 +- .../java/net/sf/jabref/gui/JabRefFrame.java | 2 +- .../java/net/sf/jabref/gui/StringDialog.java | 2 +- .../jabref/gui/entryeditor/EntryEditor.java | 2 +- .../exporter/ExportCustomizationDialog.java | 2 +- .../sf/jabref/gui/groups/GroupSelector.java | 2 +- .../net/sf/jabref/gui/help/HelpAction.java | 1 + .../gui/journals/ManageJournalsPanel.java | 2 +- .../gui/labelpattern/LabelPatternPanel.java | 2 +- .../maintable/MainTableSelectionListener.java | 3 +- .../gui/openoffice/OpenOfficePanel.java | 2 +- .../sf/jabref/gui/preftabs/AdvancedTab.java | 2 +- .../net/sf/jabref/gui/preftabs/FileTab.java | 2 +- .../sf/jabref/gui/preftabs/GeneralTab.java | 2 +- .../jabref/gui/preftabs/NameFormatterTab.java | 2 +- .../jabref/gui/preftabs/TableColumnsTab.java | 2 +- .../net/sf/jabref/gui/search/SearchBar.java | 2 +- .../importer/ImportCustomizationDialog.java | 2 +- .../importer/fetcher/ACMPortalFetcher.java | 2 +- .../jabref/importer/fetcher/ADSFetcher.java | 2 +- .../importer/fetcher/CiteSeerXFetcher.java | 2 +- .../jabref/importer/fetcher/DBLPFetcher.java | 2 +- .../jabref/importer/fetcher/DOAJFetcher.java | 2 +- .../importer/fetcher/DOItoBibTeXFetcher.java | 2 +- .../importer/fetcher/DiVAtoBibTeXFetcher.java | 2 +- .../jabref/importer/fetcher/EntryFetcher.java | 3 +- .../importer/fetcher/EntryFetchers.java | 4 +- .../jabref/importer/fetcher/GVKFetcher.java | 2 +- .../fetcher/GoogleScholarFetcher.java | 2 +- .../importer/fetcher/IEEEXploreFetcher.java | 2 +- .../importer/fetcher/INSPIREFetcher.java | 2 +- .../importer/fetcher/ISBNtoBibTeXFetcher.java | 2 +- .../importer/fetcher/MedlineFetcher.java | 2 +- .../jabref/importer/fetcher/OAI2Fetcher.java | 4 +- .../fetcher/ScienceDirectFetcher.java | 2 +- .../fetcher/SearchBasedEntryFetcher.java | 84 ++++ .../importer/fetcher/SpringerFetcher.java | 2 +- .../net/sf/jabref/logic/fulltext/ArXiv.java | 113 ------ .../jabref/logic/fulltext/FullTextFinder.java | 25 -- .../jabref/{gui => logic}/help/HelpFile.java | 33 +- .../logic/importer/FetcherException.java | 30 ++ .../logic/importer/FulltextFetcher.java | 42 ++ .../FulltextFetchers.java} | 38 +- .../jabref/logic/importer/IdBasedFetcher.java | 36 ++ .../sf/jabref/logic/importer/IdFetcher.java | 36 ++ .../MimeTypeDetector.java | 21 +- .../logic/importer/SearchBasedFetcher.java | 37 ++ .../sf/jabref/logic/importer/WebFetcher.java | 41 ++ .../{fulltext => importer/fetcher}/ACS.java | 24 +- .../jabref/logic/importer/fetcher/ArXiv.java | 364 ++++++++++++++++++ .../fetcher}/DoiResolution.java | 37 +- .../fetcher}/GoogleScholar.java | 24 +- .../{fulltext => importer/fetcher}/IEEE.java | 22 +- .../fetcher}/ScienceDirect.java | 36 +- .../fetcher}/SpringerLink.java | 36 +- .../net/sf/jabref/logic/util/io/XMLUtil.java | 89 +++++ .../jabref/logic/util/strings/StringUtil.java | 10 + .../jabref/model/entry/ParsedFileField.java | 5 + .../net/sf/jabref/gui/help/HelpFileTest.java | 22 -- .../sf/jabref/logic/fulltext/ArXivTest.java | 61 --- .../logic/fulltext/FindFullTextTest.java | 48 --- .../sf/jabref/logic/help/HelpFileTest.java | 39 ++ .../logic/importer/FulltextFetchersTest.java | 66 ++++ .../MimeTypeDetectorTest.java | 21 +- .../fetcher}/ACSTest.java | 19 +- .../logic/importer/fetcher/ArXivTest.java | 163 ++++++++ .../fetcher}/DoiResolutionTest.java | 21 +- .../fetcher}/GoogleScholarTest.java | 21 +- .../fetcher}/IEEETest.java | 19 +- .../fetcher}/ScienceDirectTest.java | 19 +- .../fetcher}/SpringerLinkTest.java | 19 +- .../logic/{fulltext => importer}/empty.pdf | Bin 76 files changed, 1406 insertions(+), 403 deletions(-) create mode 100644 src/main/java/net/sf/jabref/importer/fetcher/SearchBasedEntryFetcher.java delete mode 100644 src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java delete mode 100644 src/main/java/net/sf/jabref/logic/fulltext/FullTextFinder.java rename src/main/java/net/sf/jabref/{gui => logic}/help/HelpFile.java (73%) create mode 100644 src/main/java/net/sf/jabref/logic/importer/FetcherException.java create mode 100644 src/main/java/net/sf/jabref/logic/importer/FulltextFetcher.java rename src/main/java/net/sf/jabref/logic/{fulltext/FindFullText.java => importer/FulltextFetchers.java} (53%) create mode 100644 src/main/java/net/sf/jabref/logic/importer/IdBasedFetcher.java create mode 100644 src/main/java/net/sf/jabref/logic/importer/IdFetcher.java rename src/main/java/net/sf/jabref/logic/{fulltext => importer}/MimeTypeDetector.java (52%) create mode 100644 src/main/java/net/sf/jabref/logic/importer/SearchBasedFetcher.java create mode 100644 src/main/java/net/sf/jabref/logic/importer/WebFetcher.java rename src/main/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/ACS.java (63%) create mode 100644 src/main/java/net/sf/jabref/logic/importer/fetcher/ArXiv.java rename src/main/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/DoiResolution.java (70%) rename src/main/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/GoogleScholar.java (67%) rename src/main/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/IEEE.java (77%) rename src/main/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/ScienceDirect.java (75%) rename src/main/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/SpringerLink.java (67%) delete mode 100644 src/test/java/net/sf/jabref/gui/help/HelpFileTest.java delete mode 100644 src/test/java/net/sf/jabref/logic/fulltext/ArXivTest.java delete mode 100644 src/test/java/net/sf/jabref/logic/fulltext/FindFullTextTest.java create mode 100644 src/test/java/net/sf/jabref/logic/help/HelpFileTest.java create mode 100644 src/test/java/net/sf/jabref/logic/importer/FulltextFetchersTest.java rename src/test/java/net/sf/jabref/logic/{fulltext => importer}/MimeTypeDetectorTest.java (74%) rename src/test/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/ACSTest.java (64%) create mode 100644 src/test/java/net/sf/jabref/logic/importer/fetcher/ArXivTest.java rename src/test/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/DoiResolutionTest.java (66%) rename src/test/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/GoogleScholarTest.java (66%) rename src/test/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/IEEETest.java (80%) rename src/test/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/ScienceDirectTest.java (65%) rename src/test/java/net/sf/jabref/logic/{fulltext => importer/fetcher}/SpringerLinkTest.java (60%) rename src/test/resources/net/sf/jabref/logic/{fulltext => importer}/empty.pdf (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c38e5bb790b5..78f5ca1e4631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Added ISBN integrity checker - Added filter to not show selected integrity checks - Enhance the entry customization dialog to give better visual feedback +- The arXiv fetcher now also supports free-text search queries ### Fixed - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly diff --git a/src/main/java/net/sf/jabref/external/FindFullTextAction.java b/src/main/java/net/sf/jabref/external/FindFullTextAction.java index f48c440de456..4631172eec62 100644 --- a/src/main/java/net/sf/jabref/external/FindFullTextAction.java +++ b/src/main/java/net/sf/jabref/external/FindFullTextAction.java @@ -26,7 +26,7 @@ import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.gui.worker.AbstractWorker; -import net.sf.jabref.logic.fulltext.FindFullText; +import net.sf.jabref.logic.importer.FulltextFetchers; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -59,7 +59,7 @@ public void init() throws Throwable { public void run() { // TODO: just download for all entries and save files without dialog entry = basePanel.getSelectedEntries().get(0); - FindFullText fft = new FindFullText(); + FulltextFetchers fft = new FulltextFetchers(); result = fft.findFullTextPDF(entry); } diff --git a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java index 282d1fbe1b65..c62f23156ead 100644 --- a/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java +++ b/src/main/java/net/sf/jabref/gui/ContentSelectorDialog2.java @@ -44,9 +44,9 @@ import net.sf.jabref.MetaData; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinder; import net.sf.jabref.gui.util.FocusRequester; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.FieldName; diff --git a/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java b/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java index a688fe08cc52..80b76812e7c2 100644 --- a/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java +++ b/src/main/java/net/sf/jabref/gui/GenFieldsCustomizer.java @@ -38,8 +38,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.preferences.JabRefPreferences; diff --git a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java index 4e09e52a7db9..642700e69f2f 100644 --- a/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/ImportInspectionDialog.java @@ -76,7 +76,6 @@ import net.sf.jabref.gui.groups.GroupTreeNodeViewModel; import net.sf.jabref.gui.groups.UndoableChangeEntriesOfGroup; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.renderer.GeneralRenderer; import net.sf.jabref.gui.undo.NamedCompound; @@ -90,6 +89,7 @@ import net.sf.jabref.logic.groups.AllEntriesGroup; import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.groups.GroupTreeNode; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.util.UpdateField; @@ -1428,7 +1428,7 @@ public Object getColumnValue(BibEntry entry, int i) { FileListTableModel model = new FileListTableModel(); entry.getFieldOptional(FieldName.FILE).ifPresent(model::setContent); fileLabel.setToolTipText(model.getToolTipHTMLRepresentation()); - if (model.getRowCount() > 0) { + if (model.getRowCount() > 0 && model.getEntry(0).type.isPresent()) { fileLabel.setIcon(model.getEntry(0).type.get().getIcon()); } return fileLabel; diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index 43eb7976d417..2de64c99ae20 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -99,7 +99,6 @@ import net.sf.jabref.gui.help.AboutAction; import net.sf.jabref.gui.help.AboutDialog; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.journals.ManageJournalsAction; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.keyboard.KeyBindingRepository; @@ -119,6 +118,7 @@ import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fetcher.GeneralFetcher; import net.sf.jabref.logic.CustomEntryTypesManager; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.logging.GuiAppender; import net.sf.jabref.logic.preferences.LastFocusedTabPreferences; diff --git a/src/main/java/net/sf/jabref/gui/StringDialog.java b/src/main/java/net/sf/jabref/gui/StringDialog.java index 50a5d4ec512b..7562b6defd4f 100644 --- a/src/main/java/net/sf/jabref/gui/StringDialog.java +++ b/src/main/java/net/sf/jabref/gui/StringDialog.java @@ -48,7 +48,6 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.undo.UndoableInsertString; import net.sf.jabref.gui.undo.UndoableRemoveString; @@ -57,6 +56,7 @@ import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; import net.sf.jabref.logic.bibtex.comparator.BibtexStringComparator; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.KeyCollisionException; diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 24fb2cb53f25..a1baa112a4bc 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -79,7 +79,6 @@ import net.sf.jabref.gui.fieldeditors.JTextAreaWithHighlighting; import net.sf.jabref.gui.fieldeditors.TextField; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.menus.ChangeEntryTypeMenu; import net.sf.jabref.gui.undo.NamedCompound; @@ -97,6 +96,7 @@ import net.sf.jabref.logic.bibtex.BibEntryWriter; import net.sf.jabref.logic.bibtex.LatexFieldFormatter; import net.sf.jabref.logic.bibtex.LatexFieldFormatterPreferences; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.search.SearchQueryHighlightListener; diff --git a/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java index 6d9e228ebb8d..df1399a351b2 100644 --- a/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/gui/exporter/ExportCustomizationDialog.java @@ -40,9 +40,9 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.util.FocusRequester; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import ca.odell.glazedlists.gui.TableFormat; diff --git a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java index 247f3cc3b0a6..289a5ae0a946 100644 --- a/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/net/sf/jabref/gui/groups/GroupSelector.java @@ -65,7 +65,6 @@ import net.sf.jabref.gui.SidePaneComponent; import net.sf.jabref.gui.SidePaneManager; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.maintable.MainTableDataModel; import net.sf.jabref.gui.undo.NamedCompound; import net.sf.jabref.gui.worker.AbstractWorker; @@ -74,6 +73,7 @@ import net.sf.jabref.logic.groups.EntriesGroupChange; import net.sf.jabref.logic.groups.GroupTreeNode; import net.sf.jabref.logic.groups.MoveGroupChange; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.search.SearchMatcher; import net.sf.jabref.logic.search.matchers.MatcherSet; diff --git a/src/main/java/net/sf/jabref/gui/help/HelpAction.java b/src/main/java/net/sf/jabref/gui/help/HelpAction.java index a01103f81613..3be2e2c5059a 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpAction.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpAction.java @@ -27,6 +27,7 @@ import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.actions.MnemonicAwareAction; import net.sf.jabref.gui.desktop.JabRefDesktop; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.preferences.JabRefPreferences; diff --git a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java index 4fc7f667a02e..5bab110bf889 100644 --- a/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java +++ b/src/main/java/net/sf/jabref/gui/journals/ManageJournalsPanel.java @@ -61,9 +61,9 @@ import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.net.MonitoredURLDownload; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.journals.Abbreviation; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; diff --git a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java index f1a96fe418bd..19ef372d409b 100644 --- a/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java +++ b/src/main/java/net/sf/jabref/gui/labelpattern/LabelPatternPanel.java @@ -35,7 +35,7 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.AbstractLabelPattern; import net.sf.jabref.logic.labelpattern.DatabaseLabelPattern; diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java index 8068fa6933ff..2f6243894902 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableSelectionListener.java @@ -35,6 +35,7 @@ import net.sf.jabref.JabRefExecutorService; import net.sf.jabref.JabRefGUI; import net.sf.jabref.external.ExternalFileMenuItem; +import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.BasePanelMode; import net.sf.jabref.gui.FileListEntry; @@ -318,7 +319,7 @@ public void mouseClicked(MouseEvent e) { } if (flEntry != null) { ExternalFileMenuItem item = new ExternalFileMenuItem(panel.frame(), entry, "", - flEntry.link, flEntry.type.get().getIcon(), + flEntry.link, flEntry.type.map(ExternalFileType::getIcon).orElse(null), panel.getBibDatabaseContext(), flEntry.type); boolean success = item.openLink(); if (!success) { diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java index 891540870406..4146581d2737 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java @@ -53,9 +53,9 @@ import net.sf.jabref.gui.SidePaneManager; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.openoffice.OOBibStyle; import net.sf.jabref.logic.openoffice.OpenOfficePreferences; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java index b2b78cfbd872..90b20dbfb8d0 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/AdvancedTab.java @@ -27,8 +27,8 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.remote.JabRefMessageHandler; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.remote.RemotePreferences; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java index fbd93aeac6d6..d03529707e8b 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/FileTab.java @@ -35,7 +35,7 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java b/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java index b8fbb4bc154e..99284d2b1862 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/GeneralTab.java @@ -34,7 +34,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Encodings; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseMode; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java b/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java index 6cf2b967b3e2..065a5c2745b5 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/NameFormatterTab.java @@ -38,7 +38,7 @@ import net.sf.jabref.gui.IconTheme; import net.sf.jabref.gui.OSXCompatibleToolbar; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.format.NameFormatter; import net.sf.jabref.preferences.JabRefPreferences; diff --git a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java index f93b80d7f8f6..1656291ea6c5 100644 --- a/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java +++ b/src/main/java/net/sf/jabref/gui/preftabs/TableColumnsTab.java @@ -52,7 +52,7 @@ import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.OSXCompatibleToolbar; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibtexSingleField; import net.sf.jabref.model.entry.InternalBibtexFields; diff --git a/src/main/java/net/sf/jabref/gui/search/SearchBar.java b/src/main/java/net/sf/jabref/gui/search/SearchBar.java index 5cde5ab7df3b..821121891c6b 100644 --- a/src/main/java/net/sf/jabref/gui/search/SearchBar.java +++ b/src/main/java/net/sf/jabref/gui/search/SearchBar.java @@ -39,11 +39,11 @@ import net.sf.jabref.gui.WrapLayout; import net.sf.jabref.gui.autocompleter.AutoCompleteSupport; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.maintable.MainTableDataModel; import net.sf.jabref.gui.util.component.JTextFieldWithUnfocusedText; import net.sf.jabref.gui.worker.AbstractWorker; import net.sf.jabref.logic.autocompleter.AutoCompleter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.search.SearchQueryHighlightObservable; diff --git a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java index 3631ea391f06..b7f9d99af892 100644 --- a/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/importer/ImportCustomizationDialog.java @@ -47,10 +47,10 @@ import net.sf.jabref.gui.FileDialogs; import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.help.HelpAction; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.importer.fileformat.ImportFormat; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.preferences.JabRefPreferences; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java index 44fcaf7b6726..2e9e8ab217c6 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ACMPortalFetcher.java @@ -43,13 +43,13 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.FetcherPreviewDialog; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java index b8818deab06f..b6b93b339b34 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ADSFetcher.java @@ -39,11 +39,11 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java index b1f8e14876e7..2a462fc789d7 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/CiteSeerXFetcher.java @@ -26,10 +26,10 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java index 320b47b07e56..d45b978f4c9c 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DBLPFetcher.java @@ -25,10 +25,10 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.DuplicateCheck; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java index ca5ec8b44d55..22482e1d461c 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOAJFetcher.java @@ -18,10 +18,10 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.JSONEntryParser; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java index ed05b13c537e..9004eadb3d62 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DOItoBibTeXFetcher.java @@ -10,13 +10,13 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.logic.util.DOI; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java index 6695f0d53247..475ab4f0288d 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/DiVAtoBibTeXFetcher.java @@ -26,13 +26,13 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java index 709e750c7eff..f30624c99e71 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetcher.java @@ -18,9 +18,9 @@ import javax.swing.JPanel; import net.sf.jabref.gui.ImportInspectionDialog; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.logic.help.HelpFile; /** * Implement this interface to add another activeFetcher (something that grabs records @@ -34,6 +34,7 @@ * A Fetcher should not execute any GUI Operations, because it might be run in * headless mode, but rather use the OutputPrinter for talking to the user. */ +@Deprecated // use SearchBasedFetcher instead public interface EntryFetcher extends ImportInspectionDialog.CallBack { /** diff --git a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java index 8e0f7bd13b3e..7e7ce0e1a515 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java @@ -19,6 +19,7 @@ import java.util.LinkedList; import java.util.List; +import net.sf.jabref.logic.importer.fetcher.ArXiv; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; public class EntryFetchers { @@ -37,12 +38,13 @@ public EntryFetchers(JournalAbbreviationLoader abbreviationLoader) { entryFetchers.add(new INSPIREFetcher()); entryFetchers.add(new ISBNtoBibTeXFetcher()); entryFetchers.add(new MedlineFetcher()); - entryFetchers.add(new OAI2Fetcher()); + // entryFetchers.add(new OAI2Fetcher()); - new arXiv fetcher in place, see below // entryFetchers.add(new ScienceDirectFetcher()); currently not working - removed see #409 entryFetchers.add(new ACMPortalFetcher()); entryFetchers.add(new GoogleScholarFetcher()); entryFetchers.add(new DOAJFetcher()); entryFetchers.add(new SpringerFetcher()); + entryFetchers.add(new SearchBasedEntryFetcher(new ArXiv())); } public List getEntryFetchers() { diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java index 4e900d3719e9..24c008df3b5c 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java @@ -19,9 +19,9 @@ import javax.swing.JPanel; import javax.xml.parsers.ParserConfigurationException; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java index 5c33925e30b9..44b36eae33d7 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GoogleScholarFetcher.java @@ -34,11 +34,11 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.FetcherPreviewDialog; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java index f76691ee4aa3..dfa02e6f7a19 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/IEEEXploreFetcher.java @@ -36,13 +36,13 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.l10n.Localization; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java index 46cd6f3664a2..0c86a7828e7a 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/INSPIREFetcher.java @@ -28,11 +28,11 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java index 8cfc6a58b5b7..fc76ba24761c 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ISBNtoBibTeXFetcher.java @@ -27,12 +27,12 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import net.sf.jabref.logic.formatter.casechanger.ProtectTermsFormatter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java index 163775150641..8f1e5b35f692 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/MedlineFetcher.java @@ -29,11 +29,11 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.fileformat.MedlineImporter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java index 0ecc84b97c88..2f4e289fb33f 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/OAI2Fetcher.java @@ -31,10 +31,10 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OAI2Handler; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -51,6 +51,8 @@ * This class can be used to access any archive offering an OAI2 interface. By * default it will access ArXiv.org * + * @see + * * @author Ulrich Stärk * @author Christian Kopf */ diff --git a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java index 6fc7724a6252..5d996acd075e 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/ScienceDirectFetcher.java @@ -27,9 +27,9 @@ import javax.swing.JPanel; import net.sf.jabref.Globals; -import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.net.URLDownload; diff --git a/src/main/java/net/sf/jabref/importer/fetcher/SearchBasedEntryFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/SearchBasedEntryFetcher.java new file mode 100644 index 000000000000..1ecd62a783f2 --- /dev/null +++ b/src/main/java/net/sf/jabref/importer/fetcher/SearchBasedEntryFetcher.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2003-2016 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.importer.fetcher; + +import java.util.List; +import java.util.Objects; + +import javax.swing.JPanel; + +import net.sf.jabref.importer.ImportInspector; +import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.logic.help.HelpFile; +import net.sf.jabref.logic.importer.FetcherException; +import net.sf.jabref.logic.importer.SearchBasedFetcher; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.BibEntry; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Wrapper around {@link SearchBasedFetcher} which implements the old {@link EntryFetcher} interface. + */ +public class SearchBasedEntryFetcher implements EntryFetcher{ + + private static final Log LOGGER = LogFactory.getLog(SearchBasedEntryFetcher.class); + private final SearchBasedFetcher fetcher; + + public SearchBasedEntryFetcher(SearchBasedFetcher fetcher) { + this.fetcher = Objects.requireNonNull(fetcher); + } + + @Override + public boolean processQuery(String query, ImportInspector inspector, OutputPrinter status) { + + status.setStatus(Localization.lang("Processing %0", query)); + try { + List matches = fetcher.performSearch(query); + matches.forEach(inspector::addEntry); + return !matches.isEmpty(); + } catch (FetcherException e) { + status.setStatus(Localization.lang("Error while fetching from %0", fetcher.getName())); + LOGGER.error("Error while fetching from" + fetcher.getName(), e); + } + + return false; + } + + @Override + public String getTitle() { + return fetcher.getName(); + } + + @Override + public HelpFile getHelpPage() { + return fetcher.getHelpPage(); + } + + @Override + public JPanel getOptionsPanel() { + // not supported + return null; + } + + @Override + public void stopFetching() { + // not supported + } +} diff --git a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java index 2b23c1f24683..430be4f2c881 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/SpringerFetcher.java @@ -19,10 +19,10 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; - import net.sf.jabref.gui.help.HelpFile; import net.sf.jabref.importer.ImportInspector; import net.sf.jabref.importer.OutputPrinter; import net.sf.jabref.importer.fileformat.JSONEntryParser; + import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java b/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java deleted file mode 100644 index 6532c0a3930c..000000000000 --- a/src/main/java/net/sf/jabref/logic/fulltext/ArXiv.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.sf.jabref.logic.fulltext; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Objects; -import java.util.Optional; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import net.sf.jabref.logic.util.DOI; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; - -import com.mashape.unirest.http.HttpResponse; -import com.mashape.unirest.http.Unirest; -import com.mashape.unirest.http.exceptions.UnirestException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -/** - * FullTextFinder implementation that attempts to find a PDF URL at arXiv. - * - * @see http://arxiv.org/help/api/index - */ -public class ArXiv implements FullTextFinder { - private static final Log LOGGER = LogFactory.getLog(ArXiv.class); - - private static final String API_URL = "http://export.arxiv.org/api/query"; - - @Override - public Optional findFullText(BibEntry entry) throws IOException { - Objects.requireNonNull(entry); - Optional pdfLink = Optional.empty(); - - // 1. DOI - Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); - // 2. Eprint - Optional eprint = entry.getFieldOptional("eprint"); - - if (doi.isPresent()) { - String doiString = doi.get().getDOI(); - // Available in catalog? - try { - Document doc = queryApi(doiString); - - NodeList nodes = doc.getElementsByTagName("arxiv:doi"); - Node doiTag = nodes.item(0); - - if ((doiTag != null) && doiTag.getTextContent().equals(doiString)) { - // Lookup PDF link - NodeList links = doc.getElementsByTagName("link"); - - for (int i = 0; i < links.getLength(); i++) { - Node link = links.item(i); - NamedNodeMap attr = link.getAttributes(); - String rel = attr.getNamedItem("rel").getNodeValue(); - String href = attr.getNamedItem("href").getNodeValue(); - - if ("related".equals(rel) && "pdf".equals(attr.getNamedItem("title").getNodeValue())) { - pdfLink = Optional.of(new URL(href)); - LOGGER.info("Fulltext PDF found @ arXiv."); - } - } - } - } catch (UnirestException | ParserConfigurationException | SAXException | IOException e) { - LOGGER.warn("arXiv DOI API request failed", e); - } - } else if ((eprint.isPresent()) && !eprint.get().isEmpty()) { - try { - // only lookup on id field - Document doc = queryApi("id:" + eprint.get()); - - // Lookup PDF link - NodeList links = doc.getElementsByTagName("link"); - - for (int i = 0; i < links.getLength(); i++) { - Node link = links.item(i); - NamedNodeMap attr = link.getAttributes(); - String rel = attr.getNamedItem("rel").getNodeValue(); - String href = attr.getNamedItem("href").getNodeValue(); - - if ("related".equals(rel) && "pdf".equals(attr.getNamedItem("title").getNodeValue())) { - pdfLink = Optional.of(new URL(href)); - LOGGER.info("Fulltext PDF found @ arXiv."); - } - } - } catch (UnirestException | ParserConfigurationException | SAXException | IOException e) { - LOGGER.warn("arXiv eprint API request failed", e); - } - } - return pdfLink; - } - - private Document queryApi(String query) throws SAXException, ParserConfigurationException, IOException, UnirestException { - HttpResponse response = Unirest.get(API_URL) - .queryString("search_query", query) - .queryString("max_results", 1) - .asBinary(); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - - return builder.parse(response.getBody()); - } -} diff --git a/src/main/java/net/sf/jabref/logic/fulltext/FullTextFinder.java b/src/main/java/net/sf/jabref/logic/fulltext/FullTextFinder.java deleted file mode 100644 index c68f77cd89a1..000000000000 --- a/src/main/java/net/sf/jabref/logic/fulltext/FullTextFinder.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.sf.jabref.logic.fulltext; - -import java.io.IOException; -import java.net.URL; -import java.util.Optional; - -import net.sf.jabref.model.entry.BibEntry; - -/** - * This interface is used for classes that try to resolve a full-text PDF url for a BibTex entry. - * Implementing classes should specialize on specific article sites. - * See e.g. @link{http://libguides.mit.edu/apis}. - */ -@FunctionalInterface -public interface FullTextFinder { - /** - * Tries to find a fulltext URL for a given BibTex entry. - * - * @param entry The Bibtex entry - * @return The fulltext PDF URL Optional, if found, or an empty Optional if not found. - * @throws NullPointerException if no BibTex entry is given - * @throws java.io.IOException - */ - Optional findFullText(BibEntry entry) throws IOException; -} diff --git a/src/main/java/net/sf/jabref/gui/help/HelpFile.java b/src/main/java/net/sf/jabref/logic/help/HelpFile.java similarity index 73% rename from src/main/java/net/sf/jabref/gui/help/HelpFile.java rename to src/main/java/net/sf/jabref/logic/help/HelpFile.java index b3a252f4e554..7b878bc65f21 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpFile.java +++ b/src/main/java/net/sf/jabref/logic/help/HelpFile.java @@ -1,19 +1,20 @@ -/* Copyright (C) 2003-2016 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.help; +/* + * Copyright (C) 2003-2016 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.help; /** * This enum globally defines all help pages with the name of the markdown file in the help repository at Github. diff --git a/src/main/java/net/sf/jabref/logic/importer/FetcherException.java b/src/main/java/net/sf/jabref/logic/importer/FetcherException.java new file mode 100644 index 000000000000..46ae436b47b7 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/importer/FetcherException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2003-2016 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.importer; + +public class FetcherException extends Exception { + + + public FetcherException(String errorMessage, Exception cause) { + super(errorMessage, cause); + } + + public FetcherException(String errorMessage) { + super(errorMessage); + } +} diff --git a/src/main/java/net/sf/jabref/logic/importer/FulltextFetcher.java b/src/main/java/net/sf/jabref/logic/importer/FulltextFetcher.java new file mode 100644 index 000000000000..3925c2cc2bee --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/importer/FulltextFetcher.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2003-2016 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.importer; + +import java.io.IOException; +import java.net.URL; +import java.util.Optional; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * This interface is used for classes that try to resolve a full-text PDF url for a BibTex entry. + * Implementing classes should specialize on specific article sites. + * See e.g. @link{http://libguides.mit.edu/apis}. + */ +@FunctionalInterface +public interface FulltextFetcher { + /** + * Tries to find a fulltext URL for a given BibTex entry. + * + * @param entry The Bibtex entry + * @return The fulltext PDF URL Optional, if found, or an empty Optional if not found. + * @throws NullPointerException if no BibTex entry is given + * @throws java.io.IOException + */ + Optional findFullText(BibEntry entry) throws IOException; +} diff --git a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java b/src/main/java/net/sf/jabref/logic/importer/FulltextFetchers.java similarity index 53% rename from src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java rename to src/main/java/net/sf/jabref/logic/importer/FulltextFetchers.java index cf9672676e3b..34c2a8d460de 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/FindFullText.java +++ b/src/main/java/net/sf/jabref/logic/importer/FulltextFetchers.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer; import java.io.IOException; import java.net.URL; @@ -7,6 +24,13 @@ import java.util.Optional; import net.sf.jabref.importer.fetcher.CrossRef; +import net.sf.jabref.logic.importer.fetcher.ACS; +import net.sf.jabref.logic.importer.fetcher.ArXiv; +import net.sf.jabref.logic.importer.fetcher.DoiResolution; +import net.sf.jabref.logic.importer.fetcher.GoogleScholar; +import net.sf.jabref.logic.importer.fetcher.IEEE; +import net.sf.jabref.logic.importer.fetcher.ScienceDirect; +import net.sf.jabref.logic.importer.fetcher.SpringerLink; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -17,12 +41,12 @@ /** * Utility class for trying to resolve URLs to full-text PDF for articles. */ -public class FindFullText { - private static final Log LOGGER = LogFactory.getLog(FindFullText.class); +public class FulltextFetchers { + private static final Log LOGGER = LogFactory.getLog(FulltextFetchers.class); - private final List finders = new ArrayList<>(); + private final List finders = new ArrayList<>(); - public FindFullText() { + public FulltextFetchers() { // Ordering is important, authorities first! // Publisher finders.add(new DoiResolution()); @@ -35,7 +59,7 @@ public FindFullText() { finders.add(new GoogleScholar()); } - public FindFullText(List fetcher) { + public FulltextFetchers(List fetcher) { finders.addAll(fetcher); } @@ -48,7 +72,7 @@ public Optional findFullTextPDF(BibEntry entry) { CrossRef.findDOI(clonedEntry).ifPresent(e -> clonedEntry.setField(FieldName.DOI, e.getDOI())); } - for (FullTextFinder finder : finders) { + for (FulltextFetcher finder : finders) { try { Optional result = finder.findFullText(clonedEntry); diff --git a/src/main/java/net/sf/jabref/logic/importer/IdBasedFetcher.java b/src/main/java/net/sf/jabref/logic/importer/IdBasedFetcher.java new file mode 100644 index 000000000000..f6c4c2e8b17e --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/importer/IdBasedFetcher.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003-2016 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.importer; + +import java.util.Optional; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * Searches web resources for bibliographic information based on an identifier. + */ +public interface IdBasedFetcher extends WebFetcher { + + /** + * Looks for bibliographic information associated to the given identifier. + * + * @param identifier a string which uniquely identifies the item + * @return a {@link BibEntry} containing the bibliographic information (or an empty optional if no data was found) + */ + Optional performSearchById(String identifier) throws FetcherException; +} diff --git a/src/main/java/net/sf/jabref/logic/importer/IdFetcher.java b/src/main/java/net/sf/jabref/logic/importer/IdFetcher.java new file mode 100644 index 000000000000..e5e488a882de --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/importer/IdFetcher.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003-2016 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.importer; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * Looks for article identifier based on already present bibliographic information. + */ +public interface IdFetcher { + + /** + * Looks for an identifier based on the information stored in the given {@link BibEntry} and + * then updates the {@link BibEntry} with the found id. + * + * @param entry the {@link BibEntry} for which an identifier should be found + * @return an updated {@link BibEntry} containing the identifier (if an ID was found, otherwise the {@link BibEntry} + * is left unchanged) + */ + BibEntry updateIdentfier(BibEntry entry); +} diff --git a/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java b/src/main/java/net/sf/jabref/logic/importer/MimeTypeDetector.java similarity index 52% rename from src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java rename to src/main/java/net/sf/jabref/logic/importer/MimeTypeDetector.java index e96269a6d09e..418ea934449e 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/MimeTypeDetector.java +++ b/src/main/java/net/sf/jabref/logic/importer/MimeTypeDetector.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer; import java.io.IOException; import java.net.URL; @@ -27,4 +44,4 @@ private static Optional getMimeType(String url) { return Optional.empty(); } } -} \ No newline at end of file +} diff --git a/src/main/java/net/sf/jabref/logic/importer/SearchBasedFetcher.java b/src/main/java/net/sf/jabref/logic/importer/SearchBasedFetcher.java new file mode 100644 index 000000000000..d53685df5915 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/importer/SearchBasedFetcher.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2003-2016 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.importer; + +import java.util.List; + +import net.sf.jabref.model.entry.BibEntry; + +/** + * Searches web resources for bibliographic information based on a free-text query. + * May return multiple search hits. + */ +public interface SearchBasedFetcher extends WebFetcher { + + /** + * Looks for hits which are matched by the given free-text query. + * + * @param query search string + * @return a list of {@link BibEntry}, which are matched by the query (may be empty) + */ + List performSearch(String query) throws FetcherException; +} diff --git a/src/main/java/net/sf/jabref/logic/importer/WebFetcher.java b/src/main/java/net/sf/jabref/logic/importer/WebFetcher.java new file mode 100644 index 000000000000..5e6c68b89a5c --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/importer/WebFetcher.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2003-2016 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.importer; + +import net.sf.jabref.logic.help.HelpFile; + +/** + * Searches web resources for bibliographic information. + */ +public interface WebFetcher { + + /** + * Returns the localized name of this fetcher. + * The title can be used to display the fetcher in the menu and in the side pane. + * + * @return the localized name + */ + String getName(); + + /** + * Returns the help page for this fetcher. + * + * @return the {@link HelpFile} enum constant for the help page + */ + HelpFile getHelpPage(); +} diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ACS.java b/src/main/java/net/sf/jabref/logic/importer/fetcher/ACS.java similarity index 63% rename from src/main/java/net/sf/jabref/logic/fulltext/ACS.java rename to src/main/java/net/sf/jabref/logic/importer/fetcher/ACS.java index 97c8ad144227..62eb86c76007 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ACS.java +++ b/src/main/java/net/sf/jabref/logic/importer/fetcher/ACS.java @@ -1,10 +1,28 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; import java.util.Objects; import java.util.Optional; +import net.sf.jabref.logic.importer.FulltextFetcher; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -16,9 +34,9 @@ import org.jsoup.nodes.Element; /** - * FullTextFinder implementation that attempts to find a PDF URL at ACS. + * FulltextFetcher implementation that attempts to find a PDF URL at ACS. */ -public class ACS implements FullTextFinder { +public class ACS implements FulltextFetcher { private static final Log LOGGER = LogFactory.getLog(ACS.class); private static final String SOURCE = "http://pubs.acs.org/doi/abs/%s"; diff --git a/src/main/java/net/sf/jabref/logic/importer/fetcher/ArXiv.java b/src/main/java/net/sf/jabref/logic/importer/fetcher/ArXiv.java new file mode 100644 index 000000000000..684c218a59d6 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/importer/fetcher/ArXiv.java @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2003-2016 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.importer.fetcher; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import net.sf.jabref.importer.fetcher.OAI2Fetcher; +import net.sf.jabref.logic.TypedBibEntry; +import net.sf.jabref.logic.help.HelpFile; +import net.sf.jabref.logic.importer.FetcherException; +import net.sf.jabref.logic.importer.FulltextFetcher; +import net.sf.jabref.logic.importer.IdBasedFetcher; +import net.sf.jabref.logic.importer.SearchBasedFetcher; +import net.sf.jabref.logic.util.DOI; +import net.sf.jabref.logic.util.io.XMLUtil; +import net.sf.jabref.logic.util.strings.StringUtil; +import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.BibtexEntryTypes; +import net.sf.jabref.model.entry.FieldName; +import net.sf.jabref.model.entry.ParsedFileField; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.client.utils.URIBuilder; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +/** + * Fetcher for the arXiv. + * + * @see ArXiv API for an overview of the API + * @see ArXiv API User's Manual for a detailed + * description on how to use the API + * + * Similar implementions: + * arxiv2bib which is live + * dspace-portalmec + */ +public class ArXiv implements FulltextFetcher, SearchBasedFetcher, IdBasedFetcher { + + private static final Log LOGGER = LogFactory.getLog(ArXiv.class); + + private static final String API_URL = "http://export.arxiv.org/api/query"; + + @Override + public Optional findFullText(BibEntry entry) throws IOException { + Objects.requireNonNull(entry); + + // 1. Eprint + Optional identifier = entry.getFieldOptional("eprint"); + if (StringUtil.isNotBlank(identifier)) { + try { + // Get pdf of entry with the specified id + Optional pdfUrl = searchForEntryById(identifier.get()).flatMap(ArXivEntry::getPdfUrl); + if (pdfUrl.isPresent()) { + LOGGER.info("Fulltext PDF found @ arXiv."); + return pdfUrl; + } + } catch (FetcherException e) { + LOGGER.warn("arXiv eprint API request failed", e); + } + } + + // 2. DOI + Optional doi = entry.getFieldOptional(FieldName.DOI).flatMap(DOI::build); + if (doi.isPresent()) { + String doiString = doi.get().getDOI(); + // Search for an entry in the ArXiv which is linked to the doi + try { + Optional pdfUrl = searchForEntry("doi:" + doiString).flatMap(ArXivEntry::getPdfUrl); + if (pdfUrl.isPresent()) { + LOGGER.info("Fulltext PDF found @ arXiv."); + return pdfUrl; + } + } catch (FetcherException e) { + LOGGER.warn("arXiv DOI API request failed", e); + } + } + + return Optional.empty(); + } + + private Optional searchForEntry(String searchQuery) throws FetcherException { + List entries = queryApi(searchQuery, Collections.emptyList(), 0, 1); + if (entries.size() == 1) { + return Optional.of(entries.get(0)); + } else { + return Optional.empty(); + } + } + + private Optional searchForEntryById(String identifier) throws FetcherException { + List entries = queryApi("", Collections.singletonList(identifier), 0, 1); + if (entries.size() == 1) { + return Optional.of(entries.get(0)); + } else { + return Optional.empty(); + } + } + + private List searchForEntries(String searchQuery) throws FetcherException { + return queryApi(searchQuery, Collections.emptyList(), 0, 10); + } + + private List queryApi(String searchQuery, List ids, int start, int maxResults) + throws FetcherException { + Document result = callApi(searchQuery, ids, start, maxResults); + List entries = XMLUtil.asList(result.getElementsByTagName("entry")); + + return entries.stream().map(ArXivEntry::new).collect(Collectors.toList()); + } + + /** + * Queries the API. + * + * If only {@code searchQuery} is given, then the API will return results for each article that matches the query. + * If only {@code ids} is given, then the API will return results for each article in the list. + * If both {@code searchQuery} and {@code ids} are given, then the API will return each article in + * {@code ids} that matches {@code searchQuery}. This allows the API to act as a results filter. + * + * @param searchQuery the search query used to find articles; + * details + * @param ids a list of arXiv identifiers + * @param start the index of the first returned result (zero-based) + * @param maxResults the number of maximal results (has to be smaller than 2000) + * @return the response from the API as a XML document (Atom 1.0) + * @throws FetcherException if there was a problem while building the URL or the API was not accessible + */ + private Document callApi(String searchQuery, List ids, int start, int maxResults) throws FetcherException { + if (maxResults > 2000) { + throw new IllegalArgumentException("The arXiv API limits the number of maximal results to be 2000"); + } + + try { + URIBuilder uriBuilder = new URIBuilder(API_URL); + // The arXiv API has problems with accents, so we remove them (i.e. Fréchet -> Frechet) + if (StringUtils.isNotBlank(searchQuery)) { + uriBuilder.addParameter("search_query", StringUtils.stripAccents(searchQuery)); + } + if (!ids.isEmpty()) { + uriBuilder.addParameter("id_list", StringUtils.join(ids, ',')); + } + uriBuilder.addParameter("start", String.valueOf(start)); + uriBuilder.addParameter("max_results", String.valueOf(maxResults)); + URL url = uriBuilder.build().toURL(); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + if (connection.getResponseCode() == 400) { + // Bad request error from server, try to get more information + throw getException(builder.parse(connection.getErrorStream())); + } else { + return builder.parse(connection.getInputStream()); + } + } catch (SAXException | ParserConfigurationException | IOException | URISyntaxException exception) { + throw new FetcherException("arXiv API request failed", exception); + } + } + + private FetcherException getException(Document error) { + List entries = XMLUtil.asList(error.getElementsByTagName("entry")); + + // Check if the API returned an error + // In case of an error, only one entry will be returned with the error information. For example: + // http://export.arxiv.org/api/query?id_list=0307015 + // + // http://arxiv.org/api/errors#incorrect_id_format_for_0307015 + // Error + // incorrect id format for 0307015 + // + if (entries.size() == 1) { + Node node = entries.get(0); + Optional id = XMLUtil.getNodeContent(node, "id"); + Boolean isError = id.map(idContent -> idContent.startsWith("http://arxiv.org/api/errors")).orElse(false); + if (isError) { + String errorMessage = XMLUtil.getNodeContent(node, "summary").orElse("Unknown error"); + return new FetcherException(errorMessage); + } + } + return new FetcherException("arXiv API request failed"); + } + + @Override + public String getName() { + return "ArXiv"; + } + + @Override + public HelpFile getHelpPage() { + return HelpFile.FETCHER_OAI2_ARXIV; + } + + @Override + public List performSearch(String query) throws FetcherException { + return searchForEntries(query).stream().map(ArXivEntry::toBibEntry).collect(Collectors.toList()); + } + + @Override + public Optional performSearchById(String identifier) throws FetcherException { + return searchForEntryById(identifier).map(ArXivEntry::toBibEntry); + } + + private static class ArXivEntry { + + private final Optional title; + private final Optional urlAbstractPage; + private final Optional publishedDate; + private final Optional abstractText; + private final List authorNames; + private final List categories; + private final Optional pdfUrl; + private final Optional doi; + private final Optional journalReferenceText; + private final Optional primaryCategory; + + public ArXivEntry(Node item) { + // see http://arxiv.org/help/api/user-manual#_details_of_atom_results_returned + + // Title of the article + // The result from the arXiv contains hard line breaks, try to remove them + title = XMLUtil.getNodeContent(item, "title").map(OAI2Fetcher::correctLineBreaks); + + // The url leading to the abstract page + urlAbstractPage = XMLUtil.getNodeContent(item, "id"); + + // Date on which the first version was published + publishedDate = XMLUtil.getNodeContent(item, "published"); + + // Abstract of the article + abstractText = XMLUtil.getNodeContent(item, "summary").map(OAI2Fetcher::correctLineBreaks).map( + String::trim); + + // Authors of the article + authorNames = new ArrayList<>(); + for (Node authorNode : XMLUtil.getNodesByName(item, "author")) { + Optional authorName = XMLUtil.getNodeContent(authorNode, "name").map(String::trim); + authorName.ifPresent(authorNames::add); + } + + // Categories (arXiv, ACM, or MSC classification) + categories = new ArrayList<>(); + for (Node categoryNode : XMLUtil.getNodesByName(item, "category")) { + Optional category = XMLUtil.getAttributeContent(categoryNode, "term"); + category.ifPresent(categories::add); + } + + // Links + Optional pdfUrlParsed = Optional.empty(); + for (Node linkNode : XMLUtil.getNodesByName(item, "link")) { + Optional linkTitle = XMLUtil.getAttributeContent(linkNode, "title"); + if (linkTitle.equals(Optional.of("pdf"))) { + pdfUrlParsed = XMLUtil.getAttributeContent(linkNode, "href").map(url -> { + try { + return new URL(url); + } catch (MalformedURLException e) { + return null; + } + }); + } + } + pdfUrl = pdfUrlParsed; + + // Associated DOI + doi = XMLUtil.getNodeContent(item, "arxiv:doi"); + + // Journal reference (as provided by the author) + journalReferenceText = XMLUtil.getNodeContent(item, "arxiv:journal_ref"); + + // Primary category + // Ex: + primaryCategory = XMLUtil.getNode(item, "arxiv:primary_category").flatMap( + node -> XMLUtil.getAttributeContent(node, "term")); + } + + /** + * Returns the url of the linked pdf + */ + public Optional getPdfUrl() { + return pdfUrl; + } + + /** + * Returns the arXiv identifier + */ + public Optional getId() { + // remove leading http://arxiv.org/abs/ from abstract url to get arXiv ID + String prefix = "http://arxiv.org/abs/"; + return urlAbstractPage.map(abstractUrl -> { + if (abstractUrl.startsWith(prefix)) { + return abstractUrl.substring(prefix.length()); + } else { + return abstractUrl; + } + }); + } + + /** + * Returns the date when the first version was put on the arXiv + */ + public Optional getDate() { + // Publication string also contains time, e.g. 2014-05-09T14:49:43Z + return publishedDate.map(date -> { + if (date.length() < 10) { + return null; + } else { + return date.substring(0, 10); + } + }); + } + + public BibEntry toBibEntry() { + BibEntry bibEntry = new BibEntry(); + bibEntry.setType(BibtexEntryTypes.ARTICLE); + bibEntry.setField("eprinttype", "arXiv"); + bibEntry.setField("author", StringUtils.join(authorNames, " and ")); + bibEntry.setField("keywords", StringUtils.join(categories, ", ")); + getId().ifPresent(id -> bibEntry.setField("eprint", id)); + title.ifPresent(title -> bibEntry.setField("title", title)); + doi.ifPresent(doi -> bibEntry.setField("doi", doi)); + abstractText.ifPresent(abstractText -> bibEntry.setField("abstract", abstractText)); + getDate().ifPresent(date -> bibEntry.setField("date", date)); + primaryCategory.ifPresent(category -> bibEntry.setField("eprintclass", category)); + journalReferenceText.ifPresent(journal -> bibEntry.setField("journaltitle", journal)); + getPdfUrl().ifPresent(url -> (new TypedBibEntry(bibEntry, BibDatabaseMode.BIBLATEX)) + .setFiles(Collections.singletonList(new ParsedFileField("online", url, "PDF")))); + + return bibEntry; + } + } +} diff --git a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java b/src/main/java/net/sf/jabref/logic/importer/fetcher/DoiResolution.java similarity index 70% rename from src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java rename to src/main/java/net/sf/jabref/logic/importer/fetcher/DoiResolution.java index d0ffe6af655f..f1224d2a9d39 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/DoiResolution.java +++ b/src/main/java/net/sf/jabref/logic/importer/fetcher/DoiResolution.java @@ -1,19 +1,20 @@ -/* Copyright (C) 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. +/* + * Copyright (C) 2003-2016 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.fulltext; +package net.sf.jabref.logic.importer.fetcher; import java.io.IOException; import java.net.URL; @@ -22,6 +23,8 @@ import java.util.Objects; import java.util.Optional; +import net.sf.jabref.logic.importer.FulltextFetcher; +import net.sf.jabref.logic.importer.MimeTypeDetector; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -35,9 +38,9 @@ import org.jsoup.select.Elements; /** - * FullTextFinder implementation that follows the DOI resolution redirects and scans for a full-text PDF URL. + * FulltextFetcher implementation that follows the DOI resolution redirects and scans for a full-text PDF URL. */ -public class DoiResolution implements FullTextFinder { +public class DoiResolution implements FulltextFetcher { private static final Log LOGGER = LogFactory.getLog(DoiResolution.class); @Override diff --git a/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java b/src/main/java/net/sf/jabref/logic/importer/fetcher/GoogleScholar.java similarity index 67% rename from src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java rename to src/main/java/net/sf/jabref/logic/importer/fetcher/GoogleScholar.java index a3a2647b2123..793ba64cb77c 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/GoogleScholar.java +++ b/src/main/java/net/sf/jabref/logic/importer/fetcher/GoogleScholar.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; @@ -7,6 +24,7 @@ import java.util.Objects; import java.util.Optional; +import net.sf.jabref.logic.importer.FulltextFetcher; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -17,9 +35,9 @@ import org.jsoup.select.Elements; /** - * FullTextFinder implementation that attempts to find a PDF URL at GoogleScholar. + * FulltextFetcher implementation that attempts to find a PDF URL at GoogleScholar. */ -public class GoogleScholar implements FullTextFinder { +public class GoogleScholar implements FulltextFetcher { private static final Log LOGGER = LogFactory.getLog(GoogleScholar.class); private static final String SEARCH_URL = "https://scholar.google.com//scholar?as_q=&as_epq=%s&as_occt=title"; diff --git a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java b/src/main/java/net/sf/jabref/logic/importer/fetcher/IEEE.java similarity index 77% rename from src/main/java/net/sf/jabref/logic/fulltext/IEEE.java rename to src/main/java/net/sf/jabref/logic/importer/fetcher/IEEE.java index b4262d9730a6..1906d9d1dc04 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/IEEE.java +++ b/src/main/java/net/sf/jabref/logic/importer/fetcher/IEEE.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; @@ -8,6 +25,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.sf.jabref.logic.importer.FulltextFetcher; import net.sf.jabref.logic.net.URLDownload; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; @@ -21,7 +39,7 @@ * Will first look for URLs of the type http://ieeexplore.ieee.org/stamp/stamp.jsp?[tp=&]arnumber=... * If not found, will resolve the DOI, if it starts with 10.1109, and try to find a similar link on the HTML page */ -public class IEEE implements FullTextFinder { +public class IEEE implements FulltextFetcher { private static final Log LOGGER = LogFactory.getLog(IEEE.class); private static final Pattern STAMP_PATTERN = Pattern.compile("(/stamp/stamp.jsp\\?t?p?=?&?arnumber=[0-9]+)"); diff --git a/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java b/src/main/java/net/sf/jabref/logic/importer/fetcher/ScienceDirect.java similarity index 75% rename from src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java rename to src/main/java/net/sf/jabref/logic/importer/fetcher/ScienceDirect.java index a7036577859c..e46a80d511be 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/ScienceDirect.java +++ b/src/main/java/net/sf/jabref/logic/importer/fetcher/ScienceDirect.java @@ -1,25 +1,27 @@ -/* Copyright (C) 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. +/* + * Copyright (C) 2003-2016 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.fulltext; +package net.sf.jabref.logic.importer.fetcher; import java.io.IOException; import java.net.URL; import java.util.Objects; import java.util.Optional; +import net.sf.jabref.logic.importer.FulltextFetcher; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -38,11 +40,11 @@ import org.jsoup.nodes.Element; /** - * FullTextFinder implementation that attempts to find a PDF URL at ScienceDirect. + * FulltextFetcher implementation that attempts to find a PDF URL at ScienceDirect. * * @see http://dev.elsevier.com/ */ -public class ScienceDirect implements FullTextFinder { +public class ScienceDirect implements FulltextFetcher { private static final Log LOGGER = LogFactory.getLog(ScienceDirect.class); private static final String API_URL = "http://api.elsevier.com/content/article/doi/"; diff --git a/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java b/src/main/java/net/sf/jabref/logic/importer/fetcher/SpringerLink.java similarity index 67% rename from src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java rename to src/main/java/net/sf/jabref/logic/importer/fetcher/SpringerLink.java index 4136bd469fde..9125fcb5637d 100644 --- a/src/main/java/net/sf/jabref/logic/fulltext/SpringerLink.java +++ b/src/main/java/net/sf/jabref/logic/importer/fetcher/SpringerLink.java @@ -1,25 +1,27 @@ -/* 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. +/* + * Copyright (C) 2003-2016 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.fulltext; +package net.sf.jabref.logic.importer.fetcher; import java.io.IOException; import java.net.URL; import java.util.Objects; import java.util.Optional; +import net.sf.jabref.logic.importer.FulltextFetcher; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -33,11 +35,11 @@ import org.json.JSONObject; /** - * FullTextFinder implementation that attempts to find a PDF URL at SpringerLink. + * FulltextFetcher implementation that attempts to find a PDF URL at SpringerLink. * * Uses Springer API, see @link{https://dev.springer.com} */ -public class SpringerLink implements FullTextFinder { +public class SpringerLink implements FulltextFetcher { private static final Log LOGGER = LogFactory.getLog(SpringerLink.class); private static final String API_URL = "http://api.springer.com/meta/v1/json"; diff --git a/src/main/java/net/sf/jabref/logic/util/io/XMLUtil.java b/src/main/java/net/sf/jabref/logic/util/io/XMLUtil.java index 1d336e3c471d..8c4f3c277761 100644 --- a/src/main/java/net/sf/jabref/logic/util/io/XMLUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/io/XMLUtil.java @@ -1,6 +1,11 @@ package net.sf.jabref.logic.util.io; import java.io.StringWriter; +import java.util.AbstractList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.RandomAccess; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; @@ -12,6 +17,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * Currently used for debugging only @@ -37,4 +46,84 @@ public static void printDocument(Document doc) { } } + public static List asList(NodeList n) { + return n.getLength() == 0 ? Collections.emptyList() : new NodeListWrapper(n); + } + + /** + * Gets the content of a subnode. + * For example, + * + * content + * + */ + public static Optional getNodeContent(Node item, String nodeName) { + if (item.getNodeType() != Node.ELEMENT_NODE) { + return Optional.empty(); + } + + NodeList metadata = ((Element) item).getElementsByTagName(nodeName); + if (metadata.getLength() == 1) { + return Optional.ofNullable(metadata.item(0).getTextContent()); + } else { + return Optional.empty(); + } + } + + /** + * Gets the content of an attribute. + * For example, + * + */ + public static Optional getAttributeContent(Node item, String attributeName) { + NamedNodeMap attributes = item.getAttributes(); + return Optional.ofNullable(attributes.getNamedItem(attributeName)).map(Node::getTextContent); + } + + /** + * Gets a list of subnodes with the specified tag name. + * For example, + * + * first hit + * second hit + * + */ + public static List getNodesByName(Node item, String nodeName) { + if (item.getNodeType() != Node.ELEMENT_NODE) { + return Collections.emptyList(); + } + NodeList nodes = ((Element) item).getElementsByTagName(nodeName); + return asList(nodes); + } + + /** + * Gets a the first subnode with the specified tag name. + * For example, + * + * hit + * second hit, but not returned + * + */ + public static Optional getNode(Node item, String nodeName) { + return getNodesByName(item, nodeName).stream().findFirst(); + } + + // Wrapper to make NodeList iterable, + // taken from StackOverflow Answer. + private static final class NodeListWrapper extends AbstractList implements RandomAccess { + + private final NodeList list; + + NodeListWrapper(NodeList list) { + this.list = list; + } + + public Node get(int index) { + return list.item(index); + } + + public int size() { + return list.getLength(); + } + } } diff --git a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java index 432d98bd26d0..2d01d852170b 100644 --- a/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/strings/StringUtil.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -25,6 +26,7 @@ import net.sf.jabref.Globals; import com.google.common.base.CharMatcher; +import org.apache.commons.lang3.StringUtils; public class StringUtil { @@ -656,4 +658,12 @@ public static String repeat(int n, char c) { public static boolean isNullOrEmpty(String toTest) { return (toTest == null || toTest.isEmpty()); } + + public static boolean isNotBlank(Optional string) { + return string.isPresent() && isNotBlank(string.get()); + } + + public static boolean isNotBlank(String string) { + return StringUtils.isNotBlank(string); + } } diff --git a/src/main/java/net/sf/jabref/model/entry/ParsedFileField.java b/src/main/java/net/sf/jabref/model/entry/ParsedFileField.java index 24a5c126d29c..68c872eee928 100644 --- a/src/main/java/net/sf/jabref/model/entry/ParsedFileField.java +++ b/src/main/java/net/sf/jabref/model/entry/ParsedFileField.java @@ -1,5 +1,6 @@ package net.sf.jabref.model.entry; +import java.net.URL; import java.util.Objects; public class ParsedFileField { @@ -16,6 +17,10 @@ public ParsedFileField(String description, String link, String fileType) { this.fileType = Objects.requireNonNull(fileType); } + public ParsedFileField(String description, URL link, String fileType) { + this(description, Objects.requireNonNull(link).toString(), fileType); + } + public String getFileType() { return fileType; } diff --git a/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java b/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java deleted file mode 100644 index 0859551bb592..000000000000 --- a/src/test/java/net/sf/jabref/gui/help/HelpFileTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.sf.jabref.gui.help; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; - -import org.junit.Test; - -import static junit.framework.TestCase.assertEquals; - -public class HelpFileTest { - private final String jabrefHelp = "http://help.jabref.org/en/"; - @Test - public void referToValidPage() throws IOException { - for (HelpFile help : HelpFile.values()) { - URL url = new URL(jabrefHelp + help.getPageName()); - HttpURLConnection http = (HttpURLConnection) url.openConnection(); - http.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64)"); - assertEquals(200, http.getResponseCode()); - } - } -} diff --git a/src/test/java/net/sf/jabref/logic/fulltext/ArXivTest.java b/src/test/java/net/sf/jabref/logic/fulltext/ArXivTest.java deleted file mode 100644 index ece4407258bb..000000000000 --- a/src/test/java/net/sf/jabref/logic/fulltext/ArXivTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.sf.jabref.logic.fulltext; - -import java.io.IOException; -import java.net.URL; -import java.util.Optional; - -import net.sf.jabref.model.entry.BibEntry; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class ArXivTest { - - private ArXiv finder; - private BibEntry entry; - - @Before - public void setUp() { - finder = new ArXiv(); - entry = new BibEntry(); - } - - @Test - public void doiNotPresent() throws IOException { - Assert.assertEquals(Optional.empty(), finder.findFullText(entry)); - } - - @Test(expected = NullPointerException.class) - public void rejectNullParameter() throws IOException { - finder.findFullText(null); - Assert.fail(); - } - - @Test - public void findByDOI() throws IOException { - entry.setField("doi", "10.1529/biophysj.104.047340"); - - Assert.assertEquals( - Optional.of(new URL("http://arxiv.org/pdf/cond-mat/0406246v1")), - finder.findFullText(entry) - ); - } - - @Test - public void findByEprint() throws IOException { - entry.setField("eprint", "1603.06570"); - - Assert.assertEquals( - Optional.of(new URL("http://arxiv.org/pdf/1603.06570v1")), - finder.findFullText(entry) - ); - } - - @Test - public void notFoundByDOI() throws IOException { - entry.setField("doi", "10.1529/unknown"); - - Assert.assertEquals(Optional.empty(), finder.findFullText(entry)); - } -} \ No newline at end of file diff --git a/src/test/java/net/sf/jabref/logic/fulltext/FindFullTextTest.java b/src/test/java/net/sf/jabref/logic/fulltext/FindFullTextTest.java deleted file mode 100644 index 33ff35f0d9d8..000000000000 --- a/src/test/java/net/sf/jabref/logic/fulltext/FindFullTextTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package net.sf.jabref.logic.fulltext; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Arrays; -import java.util.Optional; - -import net.sf.jabref.model.entry.BibEntry; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class FindFullTextTest { - private BibEntry entry; - - @Before - public void setUp() { - entry = new BibEntry(); - } - - @After - public void tearDown() { - entry = null; - } - - @Ignore - @Test - public void acceptPdfUrls() throws MalformedURLException { - URL pdfUrl = new URL("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); - FullTextFinder finder = (e) -> Optional.of(pdfUrl); - FindFullText fetcher = new FindFullText(Arrays.asList(finder)); - - assertEquals(Optional.of(pdfUrl), fetcher.findFullTextPDF(entry)); - } - - @Test - public void rejectNonPdfUrls() throws MalformedURLException { - URL pdfUrl = new URL("https://github.com/JabRef/jabref/blob/master/README.md"); - FullTextFinder finder = (e) -> Optional.of(pdfUrl); - FindFullText fetcher = new FindFullText(Arrays.asList(finder)); - - assertEquals(Optional.empty(), fetcher.findFullTextPDF(entry)); - } -} diff --git a/src/test/java/net/sf/jabref/logic/help/HelpFileTest.java b/src/test/java/net/sf/jabref/logic/help/HelpFileTest.java new file mode 100644 index 000000000000..1f132d1c5ec7 --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/help/HelpFileTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2003-2016 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.help; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +public class HelpFileTest { + private final String jabrefHelp = "http://help.jabref.org/en/"; + @Test + public void referToValidPage() throws IOException { + for (HelpFile help : HelpFile.values()) { + URL url = new URL(jabrefHelp + help.getPageName()); + HttpURLConnection http = (HttpURLConnection) url.openConnection(); + http.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64)"); + assertEquals(200, http.getResponseCode()); + } + } +} diff --git a/src/test/java/net/sf/jabref/logic/importer/FulltextFetchersTest.java b/src/test/java/net/sf/jabref/logic/importer/FulltextFetchersTest.java new file mode 100644 index 000000000000..e048b15a75a1 --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/importer/FulltextFetchersTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2003-2016 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.importer; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; +import java.util.Optional; + +import net.sf.jabref.model.entry.BibEntry; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class FulltextFetchersTest { + private BibEntry entry; + + @Before + public void setUp() { + entry = new BibEntry(); + } + + @After + public void tearDown() { + entry = null; + } + + @Ignore + @Test + public void acceptPdfUrls() throws MalformedURLException { + URL pdfUrl = new URL("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); + FulltextFetcher finder = (e) -> Optional.of(pdfUrl); + FulltextFetchers fetcher = new FulltextFetchers(Arrays.asList(finder)); + + assertEquals(Optional.of(pdfUrl), fetcher.findFullTextPDF(entry)); + } + + @Ignore // Fails on travis + @Test + public void rejectNonPdfUrls() throws MalformedURLException { + URL pdfUrl = new URL("https://github.com/JabRef/jabref/blob/master/README.md"); + FulltextFetcher finder = (e) -> Optional.of(pdfUrl); + FulltextFetchers fetcher = new FulltextFetchers(Arrays.asList(finder)); + + assertEquals(Optional.empty(), fetcher.findFullTextPDF(entry)); + } +} diff --git a/src/test/java/net/sf/jabref/logic/fulltext/MimeTypeDetectorTest.java b/src/test/java/net/sf/jabref/logic/importer/MimeTypeDetectorTest.java similarity index 74% rename from src/test/java/net/sf/jabref/logic/fulltext/MimeTypeDetectorTest.java rename to src/test/java/net/sf/jabref/logic/importer/MimeTypeDetectorTest.java index 1f984dc3e85d..9a584c086a9c 100644 --- a/src/test/java/net/sf/jabref/logic/fulltext/MimeTypeDetectorTest.java +++ b/src/test/java/net/sf/jabref/logic/importer/MimeTypeDetectorTest.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer; import java.net.URISyntaxException; @@ -68,4 +85,4 @@ public void beTrueForPDFMimeTypeVariations() { assertTrue(MimeTypeDetector.isPdfContentType(mimeTypeVariation)); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/logic/fulltext/ACSTest.java b/src/test/java/net/sf/jabref/logic/importer/fetcher/ACSTest.java similarity index 64% rename from src/test/java/net/sf/jabref/logic/fulltext/ACSTest.java rename to src/test/java/net/sf/jabref/logic/importer/fetcher/ACSTest.java index 8c1236d59fc4..344726aa720b 100644 --- a/src/test/java/net/sf/jabref/logic/fulltext/ACSTest.java +++ b/src/test/java/net/sf/jabref/logic/importer/fetcher/ACSTest.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; diff --git a/src/test/java/net/sf/jabref/logic/importer/fetcher/ArXivTest.java b/src/test/java/net/sf/jabref/logic/importer/fetcher/ArXivTest.java new file mode 100644 index 000000000000..f8c4f23b4a4c --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/importer/fetcher/ArXivTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2003-2016 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.importer.fetcher; + +import java.io.IOException; +import java.net.URL; +import java.util.Collections; +import java.util.Optional; + +import net.sf.jabref.logic.importer.FetcherException; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.BibLatexEntryTypes; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.assertEquals; + +public class ArXivTest { + + @Rule public ExpectedException expectedException = ExpectedException.none(); + private ArXiv finder; + private BibEntry entry; + private BibEntry sliceTheoremPaper; + + @Before + public void setUp() { + finder = new ArXiv(); + entry = new BibEntry(); + + sliceTheoremPaper = new BibEntry(); + sliceTheoremPaper.setType(BibLatexEntryTypes.ARTICLE); + sliceTheoremPaper.setField("author", "Tobias Diez"); + sliceTheoremPaper.setField("title", "Slice theorem for Fréchet group actions and covariant symplectic field theory"); + sliceTheoremPaper.setField("date", "2014-05-09"); + sliceTheoremPaper.setField("abstract", "A general slice theorem for the action of a Fr\\'echet Lie group on a Fr\\'echet manifolds is established. The Nash-Moser theorem provides the fundamental tool to generalize the result of Palais to this infinite-dimensional setting. The presented slice theorem is illustrated by its application to gauge theories: the action of the gauge transformation group admits smooth slices at every point and thus the gauge orbit space is stratified by Fr\\'echet manifolds. Furthermore, a covariant and symplectic formulation of classical field theory is proposed and extensively discussed. At the root of this novel framework is the incorporation of field degrees of freedom F and spacetime M into the product manifold F * M. The induced bigrading of differential forms is used in order to carry over the usual symplectic theory to this new setting. The examples of the Klein-Gordon field and general Yang-Mills theory illustrate that the presented approach conveniently handles the occurring symmetries."); + sliceTheoremPaper.setField("eprint", "1405.2249v1"); + sliceTheoremPaper.setField("file", "online:http\\://arxiv.org/pdf/1405.2249v1:PDF"); + sliceTheoremPaper.setField("eprinttype", "arXiv"); + sliceTheoremPaper.setField("eprintclass", "math-ph"); + sliceTheoremPaper.setField("keywords", "math-ph, math.DG, math.MP, math.SG, 58B99, 58Z05, 58B25, 22E65, 58D19, 53D20, 53D42"); + } + + @Test + public void doiNotPresent() throws IOException { + assertEquals(Optional.empty(), finder.findFullText(entry)); + } + + @Test(expected = NullPointerException.class) + public void rejectNullParameter() throws IOException { + finder.findFullText(null); + Assert.fail(); + } + + @Test + public void findByDOI() throws IOException { + entry.setField("doi", "10.1529/biophysj.104.047340"); + + assertEquals(Optional.of(new URL("http://arxiv.org/pdf/cond-mat/0406246v1")), finder.findFullText(entry)); + } + + @Test + public void findByEprint() throws IOException { + entry.setField("eprint", "1603.06570"); + + assertEquals(Optional.of(new URL("http://arxiv.org/pdf/1603.06570v1")), finder.findFullText(entry)); + } + + @Test + public void findByEprintWithUnknownDOI() throws IOException { + entry.setField("doi", "10.1529/unknown"); + entry.setField("eprint", "1603.06570"); + + assertEquals(Optional.of(new URL("http://arxiv.org/pdf/1603.06570v1")), finder.findFullText(entry)); + } + + @Test + public void notFoundByUnknownDOI() throws IOException { + entry.setField("doi", "10.1529/unknown"); + + assertEquals(Optional.empty(), finder.findFullText(entry)); + } + + @Test + public void notFoundByUnknownId() throws IOException { + entry.setField("eprint", "1234.12345"); + + assertEquals(Optional.empty(), finder.findFullText(entry)); + } + + @Test + public void searchEntryByPartOfTitle() throws Exception { + assertEquals(Collections.singletonList(sliceTheoremPaper), + finder.performSearch("ti:\"slice theorem for Frechet\"")); + } + + @Test + public void searchEntryByPartOfTitleWithAcuteAccent() throws Exception { + assertEquals(Collections.singletonList(sliceTheoremPaper), + finder.performSearch("ti:\"slice theorem for Fréchet\"")); + } + + @Test + public void searchEntryByOldId() throws Exception { + BibEntry expected = new BibEntry(); + expected.setType(BibLatexEntryTypes.ARTICLE); + expected.setField("author", "H1 Collaboration"); + expected.setField("title", "Multi-Electron Production at High Transverse Momenta in ep Collisions at HERA"); + expected.setField("date", "2003-07-07"); + expected.setField("abstract", "Multi-electron production is studied at high electron transverse momentum in positron- and electron-proton collisions using the H1 detector at HERA. The data correspond to an integrated luminosity of 115 pb-1. Di-electron and tri-electron event yields are measured. Cross sections are derived in a restricted phase space region dominated by photon-photon collisions. In general good agreement is found with the Standard Model predictions. However, for electron pair invariant masses above 100 GeV, three di-electron events and three tri-electron events are observed, compared to Standard Model expectations of 0.30 \\pm 0.04 and 0.23 \\pm 0.04, respectively."); + expected.setField("eprint", "hep-ex/0307015v1"); + expected.setField("file", "online:http\\://arxiv.org/pdf/hep-ex/0307015v1:PDF"); + expected.setField("eprinttype", "arXiv"); + expected.setField("eprintclass", "hep-ex"); + expected.setField("keywords", "hep-ex"); + expected.setField("doi", "10.1140/epjc/s2003-01326-x"); + expected.setField("journaltitle", "Eur.Phys.J.C31:17-29,2003"); + + assertEquals(Optional.of(expected), finder.performSearchById("hep-ex/0307015")); + } + + @Test + public void searchEntryByIdWith4DigitsAndVersion() throws Exception { + assertEquals(Optional.of(sliceTheoremPaper), finder.performSearchById("1405.2249v1")); + } + + @Test + public void searchEntryByIdWith4Digits() throws Exception { + assertEquals(Optional.of(sliceTheoremPaper), finder.performSearchById("1405.2249")); + } + + @Test + public void searchEntryByIdWith5Digits() throws Exception { + assertEquals(Optional.of( + "An Optimal Convergence Theorem for Mean Curvature Flow of Arbitrary Codimension in Hyperbolic Spaces"), + finder.performSearchById("1503.06747").flatMap(entry -> entry.getFieldOptional("title"))); + } + + @Test + public void searchWithMalformedIdThrowsException() throws Exception { + expectedException.expect(FetcherException.class); + expectedException.expectMessage("incorrect id format"); + finder.performSearchById("123412345"); + } +} diff --git a/src/test/java/net/sf/jabref/logic/fulltext/DoiResolutionTest.java b/src/test/java/net/sf/jabref/logic/importer/fetcher/DoiResolutionTest.java similarity index 66% rename from src/test/java/net/sf/jabref/logic/fulltext/DoiResolutionTest.java rename to src/test/java/net/sf/jabref/logic/importer/fetcher/DoiResolutionTest.java index 4808005ae342..09d64788a1e0 100644 --- a/src/test/java/net/sf/jabref/logic/fulltext/DoiResolutionTest.java +++ b/src/test/java/net/sf/jabref/logic/importer/fetcher/DoiResolutionTest.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; @@ -63,4 +80,4 @@ public void notFoundByDOI() throws IOException { Assert.assertEquals(Optional.empty(), finder.findFullText(entry)); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/logic/fulltext/GoogleScholarTest.java b/src/test/java/net/sf/jabref/logic/importer/fetcher/GoogleScholarTest.java similarity index 66% rename from src/test/java/net/sf/jabref/logic/fulltext/GoogleScholarTest.java rename to src/test/java/net/sf/jabref/logic/importer/fetcher/GoogleScholarTest.java index e19a3cc5b65e..b9f3252df894 100644 --- a/src/test/java/net/sf/jabref/logic/fulltext/GoogleScholarTest.java +++ b/src/test/java/net/sf/jabref/logic/importer/fetcher/GoogleScholarTest.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; @@ -56,4 +73,4 @@ public void noLinkFound() throws IOException { Assert.assertEquals(Optional.empty(), finder.findFullText(entry)); } -} \ No newline at end of file +} diff --git a/src/test/java/net/sf/jabref/logic/fulltext/IEEETest.java b/src/test/java/net/sf/jabref/logic/importer/fetcher/IEEETest.java similarity index 80% rename from src/test/java/net/sf/jabref/logic/fulltext/IEEETest.java rename to src/test/java/net/sf/jabref/logic/importer/fetcher/IEEETest.java index 95197e4c8154..a32053e4e63d 100644 --- a/src/test/java/net/sf/jabref/logic/fulltext/IEEETest.java +++ b/src/test/java/net/sf/jabref/logic/importer/fetcher/IEEETest.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; diff --git a/src/test/java/net/sf/jabref/logic/fulltext/ScienceDirectTest.java b/src/test/java/net/sf/jabref/logic/importer/fetcher/ScienceDirectTest.java similarity index 65% rename from src/test/java/net/sf/jabref/logic/fulltext/ScienceDirectTest.java rename to src/test/java/net/sf/jabref/logic/importer/fetcher/ScienceDirectTest.java index 487767fc0686..34dc7116248a 100644 --- a/src/test/java/net/sf/jabref/logic/fulltext/ScienceDirectTest.java +++ b/src/test/java/net/sf/jabref/logic/importer/fetcher/ScienceDirectTest.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; diff --git a/src/test/java/net/sf/jabref/logic/fulltext/SpringerLinkTest.java b/src/test/java/net/sf/jabref/logic/importer/fetcher/SpringerLinkTest.java similarity index 60% rename from src/test/java/net/sf/jabref/logic/fulltext/SpringerLinkTest.java rename to src/test/java/net/sf/jabref/logic/importer/fetcher/SpringerLinkTest.java index 25727d500404..d0f8c5c4ffe3 100644 --- a/src/test/java/net/sf/jabref/logic/fulltext/SpringerLinkTest.java +++ b/src/test/java/net/sf/jabref/logic/importer/fetcher/SpringerLinkTest.java @@ -1,4 +1,21 @@ -package net.sf.jabref.logic.fulltext; +/* + * Copyright (C) 2003-2016 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.importer.fetcher; import java.io.IOException; import java.net.URL; diff --git a/src/test/resources/net/sf/jabref/logic/fulltext/empty.pdf b/src/test/resources/net/sf/jabref/logic/importer/empty.pdf similarity index 100% rename from src/test/resources/net/sf/jabref/logic/fulltext/empty.pdf rename to src/test/resources/net/sf/jabref/logic/importer/empty.pdf From 23fdfe2a05e4b617ba9b9ed66708c0e1b818a0c3 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Fri, 22 Jul 2016 18:54:44 +0200 Subject: [PATCH 263/268] Added LayoutFormatterPreferences (and related files) (#1608) * Added LayoutFormatterPreferences (and related files) * Rebased * Included JournalAbbreviationLoader in LayoutPreferences --- .../java/net/sf/jabref/gui/BasePanel.java | 5 +- .../java/net/sf/jabref/gui/PreviewPanel.java | 4 +- .../gui/openoffice/OpenOfficePanel.java | 4 +- .../jabref/logic/exporter/ExportFormat.java | 13 +- .../net/sf/jabref/logic/layout/Layout.java | 8 +- .../sf/jabref/logic/layout/LayoutEntry.java | 31 ++--- .../layout/LayoutFormatterPreferences.java | 59 ++++++++++ .../sf/jabref/logic/layout/LayoutHelper.java | 11 +- .../jabref/logic/layout/format/FileLink.java | 16 +-- .../layout/format/FileLinkPreferences.java | 33 ++++++ .../logic/layout/format/NameFormatter.java | 7 +- .../format/NameFormatterPreferences.java | 31 +++++ .../logic/layout/format/WrapFileLinks.java | 16 +-- .../jabref/logic/openoffice/OOBibStyle.java | 15 +-- .../jabref/logic/openoffice/StyleLoader.java | 21 ++-- .../net/sf/jabref/logic/util/io/FileUtil.java | 4 +- .../jabref/logic/layout/LayoutEntryTest.java | 4 +- .../sf/jabref/logic/layout/LayoutTest.java | 4 +- .../logic/layout/format/FileLinkTest.java | 15 +-- .../logic/openoffice/OOBibStyleTest.java | 111 +++++++++--------- .../logic/openoffice/StyleLoaderTest.java | 77 +++++++----- 21 files changed, 308 insertions(+), 181 deletions(-) create mode 100644 src/main/java/net/sf/jabref/logic/layout/LayoutFormatterPreferences.java create mode 100644 src/main/java/net/sf/jabref/logic/layout/format/FileLinkPreferences.java create mode 100644 src/main/java/net/sf/jabref/logic/layout/format/NameFormatterPreferences.java diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 9e8e4c8839a4..75e4616323e2 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -117,6 +117,7 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.layout.Layout; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.util.UpdateField; import net.sf.jabref.logic.util.io.FileBasedLock; @@ -991,7 +992,9 @@ private void copyKeyAndTitle() { "\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); Layout layout; try { - layout = new LayoutHelper(sr, Globals.prefs, Globals.journalAbbreviationLoader).getLayoutFromText(); + layout = new LayoutHelper(sr, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, Globals.journalAbbreviationLoader)) + .getLayoutFromText(); } catch (IOException e) { LOGGER.info("Could not get layout", e); return; diff --git a/src/main/java/net/sf/jabref/gui/PreviewPanel.java b/src/main/java/net/sf/jabref/gui/PreviewPanel.java index 768e76d86f81..3e6caaa90609 100644 --- a/src/main/java/net/sf/jabref/gui/PreviewPanel.java +++ b/src/main/java/net/sf/jabref/gui/PreviewPanel.java @@ -55,6 +55,7 @@ import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.layout.Layout; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.search.SearchQueryHighlightListener; import net.sf.jabref.model.entry.BibEntry; @@ -263,7 +264,8 @@ private void updateLayout() { StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); try { layout = Optional - .of(new LayoutHelper(sr, Globals.prefs, Globals.journalAbbreviationLoader).getLayoutFromText()); + .of(new LayoutHelper(sr, LayoutFormatterPreferences.fromPreferences(Globals.prefs, + Globals.journalAbbreviationLoader)).getLayoutFromText()); } catch (IOException e) { layout = Optional.empty(); LOGGER.debug("no layout could be set", e); diff --git a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java index 4146581d2737..7b6a1cfd44e8 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java @@ -57,6 +57,7 @@ import net.sf.jabref.gui.worker.AbstractWorker; import net.sf.jabref.logic.help.HelpFile; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.logic.openoffice.OOBibStyle; import net.sf.jabref.logic.openoffice.OpenOfficePreferences; import net.sf.jabref.logic.openoffice.StyleLoader; @@ -126,7 +127,8 @@ private OpenOfficePanel() { update = new JButton(IconTheme.JabRefIcon.REFRESH.getSmallIcon()); update.setToolTipText(Localization.lang("Sync OpenOffice/LibreOffice bibliography")); preferences = new OpenOfficePreferences(Globals.prefs); - loader = new StyleLoader(preferences, Globals.prefs, Globals.journalAbbreviationLoader, + loader = new StyleLoader(preferences, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, Globals.journalAbbreviationLoader), Globals.prefs.getDefaultEncoding()); } diff --git a/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java b/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java index 9e44a4337c5e..64ca345e8f39 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java +++ b/src/main/java/net/sf/jabref/logic/exporter/ExportFormat.java @@ -34,6 +34,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.Layout; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.model.entry.BibEntry; @@ -219,7 +220,8 @@ public void performExport(final BibDatabaseContext databaseContext, final String // Print header try (Reader reader = getReader(lfFileName + ".begin.layout")) { - LayoutHelper layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); + LayoutHelper layoutHelper = new LayoutHelper(reader, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, Globals.journalAbbreviationLoader)); beginLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was cast, export filter doesn't have a begin @@ -245,7 +247,8 @@ public void performExport(final BibDatabaseContext databaseContext, final String Layout defLayout; LayoutHelper layoutHelper; try (Reader reader = getReader(lfFileName + ".layout")) { - layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); + layoutHelper = new LayoutHelper(reader, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, Globals.journalAbbreviationLoader)); defLayout = layoutHelper.getLayoutFromText(); } if (defLayout != null) { @@ -267,7 +270,8 @@ public void performExport(final BibDatabaseContext databaseContext, final String } else { try (Reader reader = getReader(lfFileName + '.' + type + ".layout")) { // We try to get a type-specific layout for this entry. - layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); + layoutHelper = new LayoutHelper(reader, LayoutFormatterPreferences + .fromPreferences(Globals.prefs, Globals.journalAbbreviationLoader)); layout = layoutHelper.getLayoutFromText(); layouts.put(type, layout); if (layout != null) { @@ -291,7 +295,8 @@ public void performExport(final BibDatabaseContext databaseContext, final String // changed section - begin (arudert) Layout endLayout = null; try (Reader reader = getReader(lfFileName + ".end.layout")) { - layoutHelper = new LayoutHelper(reader, Globals.prefs, Globals.journalAbbreviationLoader); + layoutHelper = new LayoutHelper(reader, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, Globals.journalAbbreviationLoader)); endLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was thrown, export filter doesn't have an end diff --git a/src/main/java/net/sf/jabref/logic/layout/Layout.java b/src/main/java/net/sf/jabref/logic/layout/Layout.java index 7093d8a311a3..fb32ab07a495 100644 --- a/src/main/java/net/sf/jabref/logic/layout/Layout.java +++ b/src/main/java/net/sf/jabref/logic/layout/Layout.java @@ -22,10 +22,8 @@ import java.util.regex.Pattern; import net.sf.jabref.BibDatabaseContext; -import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,7 +40,7 @@ public class Layout { private static final Log LOGGER = LogFactory.getLog(Layout.class); - public Layout(List parsedEntries, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) { + public Layout(List parsedEntries, LayoutFormatterPreferences prefs) { List tmpEntries = new ArrayList<>(parsedEntries.size()); List blockEntries = null; @@ -68,7 +66,7 @@ public Layout(List parsedEntries, JabRefPreferences prefs, JournalAbb blockEntries.add(parsedEntry); le = new LayoutEntry(blockEntries, parsedEntry.i == LayoutHelper.IS_FIELD_END ? LayoutHelper.IS_FIELD_START : LayoutHelper.IS_GROUP_START, - prefs, repositoryLoader); + prefs); tmpEntries.add(le); blockEntries = null; } else { @@ -83,7 +81,7 @@ public Layout(List parsedEntries, JabRefPreferences prefs, JournalAbb } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, prefs, repositoryLoader)); + tmpEntries.add(new LayoutEntry(parsedEntry, prefs)); } else { blockEntries.add(parsedEntry); } diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java index b434b69a7da3..1172fa871677 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java @@ -28,8 +28,6 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import net.sf.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter; -import net.sf.jabref.logic.journals.JournalAbbreviationLoader; -import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; import net.sf.jabref.logic.layout.format.AuthorAbbreviator; import net.sf.jabref.logic.layout.format.AuthorAndsCommaReplacer; import net.sf.jabref.logic.layout.format.AuthorAndsReplacer; @@ -95,7 +93,6 @@ import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -117,13 +114,10 @@ class LayoutEntry { private static final Log LOGGER = LogFactory.getLog(LayoutEntry.class); - private final JournalAbbreviationLoader repositoryLoader; + private final LayoutFormatterPreferences prefs; - private final JabRefPreferences prefs; - - public LayoutEntry(StringInt si, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) { - this.repositoryLoader = repositoryLoader; + public LayoutEntry(StringInt si, LayoutFormatterPreferences prefs) { this.prefs = prefs; type = si.i; switch (type) { @@ -143,9 +137,7 @@ public LayoutEntry(StringInt si, JabRefPreferences prefs, JournalAbbreviationLoa } } - public LayoutEntry(List parsedEntries, int layoutType, JabRefPreferences prefs, - JournalAbbreviationLoader repositoryLoader) { - this.repositoryLoader = repositoryLoader; + public LayoutEntry(List parsedEntries, int layoutType, LayoutFormatterPreferences prefs) { this.prefs = prefs; List tmpEntries = new ArrayList<>(); String blockStart = parsedEntries.get(0).s; @@ -171,7 +163,7 @@ public LayoutEntry(List parsedEntries, int layoutType, JabRefPreferen blockEntries.add(parsedEntry); int groupType = parsedEntry.i == LayoutHelper.IS_GROUP_END ? LayoutHelper.IS_GROUP_START : LayoutHelper.IS_FIELD_START; - LayoutEntry le = new LayoutEntry(blockEntries, groupType, prefs, repositoryLoader); + LayoutEntry le = new LayoutEntry(blockEntries, groupType, prefs); tmpEntries.add(le); blockEntries = null; } else { @@ -187,7 +179,7 @@ public LayoutEntry(List parsedEntries, int layoutType, JabRefPreferen } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, prefs, repositoryLoader)); + tmpEntries.add(new LayoutEntry(parsedEntry, prefs)); } else { blockEntries.add(parsedEntry); } @@ -514,7 +506,8 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { case "Iso690NamesAuthors": return new Iso690NamesAuthors(); case "JournalAbbreviator": - return new JournalAbbreviator(repositoryLoader, JournalAbbreviationPreferences.fromPreferences(prefs)); + return new JournalAbbreviator(prefs.getJournalAbbreviationLoader(), + prefs.getJournalAbbreviationPreferences()); case "LastPage": return new LastPage(); case "FormatChars": // For backward compatibility @@ -551,7 +544,7 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { case "Default": return new Default(); case "FileLink": - return new FileLink(prefs); + return new FileLink(prefs.getFileLinkPreferences()); case "Number": return new Number(); case "RisAuthors": @@ -565,7 +558,7 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { case "WrapContent": return new WrapContent(); case "WrapFileLinks": - return new WrapFileLinks(prefs); + return new WrapFileLinks(prefs.getFileLinkPreferences()); default: return new NotFoundFormatter(name); } @@ -582,15 +575,15 @@ private List getOptionalLayout(String formatterName) { List results = new ArrayList<>(formatterStrings.size()); - Map userNameFormatter = NameFormatter.getNameFormatters(prefs); + Map userNameFormatter = NameFormatter.getNameFormatters(prefs.getNameFormatterPreferences()); for (List strings : formatterStrings) { String className = strings.get(0).trim(); // Check if this is a name formatter defined by this export filter: - if (prefs.customExportNameFormatters != null) { - String contents = prefs.customExportNameFormatters.get(className); + if (prefs.getCustomExportNameFormatters() != null) { + String contents = prefs.getCustomExportNameFormatters().get(className); if (contents != null) { NameFormatter nf = new NameFormatter(); nf.setParameter(contents); diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutFormatterPreferences.java b/src/main/java/net/sf/jabref/logic/layout/LayoutFormatterPreferences.java new file mode 100644 index 000000000000..76fd6cc99001 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutFormatterPreferences.java @@ -0,0 +1,59 @@ +package net.sf.jabref.logic.layout; + +import java.util.Map; +import java.util.Objects; + +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.logic.journals.JournalAbbreviationPreferences; +import net.sf.jabref.logic.layout.format.FileLinkPreferences; +import net.sf.jabref.logic.layout.format.NameFormatterPreferences; +import net.sf.jabref.preferences.JabRefPreferences; + +public class LayoutFormatterPreferences { + + private final NameFormatterPreferences nameFormatterPreferences; + private final JournalAbbreviationPreferences journalAbbreviationPreferences; + private final FileLinkPreferences fileLinkPreferences; + private final Map customExportNameFormatters; + private final JournalAbbreviationLoader journalAbbreviationLoader; + + public LayoutFormatterPreferences(NameFormatterPreferences nameFormatterPreferences, + JournalAbbreviationPreferences journalAbbreviationPreferences, FileLinkPreferences fileLinkPreferences, + Map customExportNameFormatters, JournalAbbreviationLoader journalAbbreviationLoader) { + this.nameFormatterPreferences = nameFormatterPreferences; + this.journalAbbreviationPreferences = journalAbbreviationPreferences; + this.customExportNameFormatters = customExportNameFormatters; + this.fileLinkPreferences = fileLinkPreferences; + this.journalAbbreviationLoader = journalAbbreviationLoader; + } + + public static LayoutFormatterPreferences fromPreferences(JabRefPreferences jabRefPreferences, + JournalAbbreviationLoader journalAbbreviationLoader) { + Objects.requireNonNull(jabRefPreferences); + Objects.requireNonNull(journalAbbreviationLoader); + return new LayoutFormatterPreferences(NameFormatterPreferences.fromPreferences(jabRefPreferences), + JournalAbbreviationPreferences.fromPreferences(jabRefPreferences), + FileLinkPreferences.fromPreferences(jabRefPreferences), + jabRefPreferences.customExportNameFormatters, journalAbbreviationLoader); + } + + public NameFormatterPreferences getNameFormatterPreferences() { + return nameFormatterPreferences; + } + + public JournalAbbreviationPreferences getJournalAbbreviationPreferences() { + return journalAbbreviationPreferences; + } + + public Map getCustomExportNameFormatters() { + return customExportNameFormatters; + } + + public FileLinkPreferences getFileLinkPreferences() { + return fileLinkPreferences; + } + + public JournalAbbreviationLoader getJournalAbbreviationLoader() { + return journalAbbreviationLoader; + } +} diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java b/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java index 3dfe088d6a35..cb49be1c42ef 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutHelper.java @@ -22,9 +22,6 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.logic.journals.JournalAbbreviationLoader; -import net.sf.jabref.preferences.JabRefPreferences; - /** * Helper class to get a Layout object. * @@ -51,14 +48,12 @@ public class LayoutHelper { private final PushbackReader in; private final List parsedEntries = new ArrayList<>(); - private final JournalAbbreviationLoader repositoryLoader; - private final JabRefPreferences prefs; + private final LayoutFormatterPreferences prefs; private boolean endOfFile; - public LayoutHelper(Reader in, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) { + public LayoutHelper(Reader in, LayoutFormatterPreferences prefs) { this.in = new PushbackReader(Objects.requireNonNull(in)); - this.repositoryLoader = Objects.requireNonNull(repositoryLoader); this.prefs = Objects.requireNonNull(prefs); } @@ -73,7 +68,7 @@ public Layout getLayoutFromText() throws IOException { } } - return new Layout(parsedEntries, prefs, repositoryLoader); + return new Layout(parsedEntries, prefs); } public static String getCurrentGroup() { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java index 3c161db06529..63e2e2f6dd47 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/FileLink.java @@ -17,17 +17,13 @@ import java.io.File; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Optional; -import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.ParamLayoutFormatter; import net.sf.jabref.logic.util.io.FileUtil; -import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -41,11 +37,11 @@ public class FileLink implements ParamLayoutFormatter { private static final Log LOGGER = LogFactory.getLog(FileLink.class); private String fileType; - private final JabRefPreferences prefs; + private final FileLinkPreferences prefs; - public FileLink(JabRefPreferences prefs) { - this.prefs = prefs; + public FileLink(FileLinkPreferences fileLinkPreferences) { + this.prefs = fileLinkPreferences; } @Override @@ -82,10 +78,10 @@ public String format(String field) { // but that is not available from a formatter. Therefore, as an // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: - if (prefs.fileDirForDatabase == null) { - dirs = Collections.singletonList(prefs.get(FieldName.FILE + Globals.DIR_SUFFIX)); + if (prefs.getFileDirForDatabase() == null) { + dirs = prefs.getGeneratedDirForDatabase(); } else { - dirs = prefs.fileDirForDatabase; + dirs = prefs.getFileDirForDatabase(); } Optional f = FileUtil.expandFilename(link, dirs); diff --git a/src/main/java/net/sf/jabref/logic/layout/format/FileLinkPreferences.java b/src/main/java/net/sf/jabref/logic/layout/format/FileLinkPreferences.java new file mode 100644 index 000000000000..6f6822253452 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/layout/format/FileLinkPreferences.java @@ -0,0 +1,33 @@ +package net.sf.jabref.logic.layout.format; + +import java.util.Collections; +import java.util.List; + +import net.sf.jabref.Globals; +import net.sf.jabref.model.entry.FieldName; +import net.sf.jabref.preferences.JabRefPreferences; + +public class FileLinkPreferences { + + private final List generatedDirForDatabase; + private final List fileDirForDatabase; + + + public FileLinkPreferences(List generatedDirForDatabase, List fileDirForDatabase) { + this.generatedDirForDatabase = generatedDirForDatabase; + this.fileDirForDatabase = fileDirForDatabase; + } + + public static FileLinkPreferences fromPreferences(JabRefPreferences prefs) { + return new FileLinkPreferences(Collections.singletonList(prefs.get(FieldName.FILE + Globals.DIR_SUFFIX)), + prefs.fileDirForDatabase); + } + + public List getGeneratedDirForDatabase() { + return generatedDirForDatabase; + } + + public List getFileDirForDatabase() { + return fileDirForDatabase; + } +} diff --git a/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java index 1cc455bf7e1b..da2b8b34daad 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatter.java @@ -22,7 +22,6 @@ import net.sf.jabref.logic.bst.BibtexNameFormatter; import net.sf.jabref.logic.layout.LayoutFormatter; import net.sf.jabref.model.entry.AuthorList; -import net.sf.jabref.preferences.JabRefPreferences; /** * This layout formatter uses the Bibtex name.format$ method and provides ultimate flexibility: @@ -184,12 +183,12 @@ public void setParameter(String parameter) { this.parameter = parameter; } - public static Map getNameFormatters(JabRefPreferences prefs) { + public static Map getNameFormatters(NameFormatterPreferences prefs) { Map result = new HashMap<>(); - List names = prefs.getStringList(NameFormatter.NAME_FORMATER_KEY); - List formats = prefs.getStringList(NameFormatter.NAME_FORMATTER_VALUE); + List names = prefs.getNameFormatterKey(); + List formats = prefs.getNameFormatterValue(); for (int i = 0; i < names.size(); i++) { if (i < formats.size()) { diff --git a/src/main/java/net/sf/jabref/logic/layout/format/NameFormatterPreferences.java b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatterPreferences.java new file mode 100644 index 000000000000..2c6a9b748b81 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/layout/format/NameFormatterPreferences.java @@ -0,0 +1,31 @@ +package net.sf.jabref.logic.layout.format; + +import java.util.List; + +import net.sf.jabref.preferences.JabRefPreferences; + +public class NameFormatterPreferences { + + private final List nameFormatterKey; + private final List nameFormatterValue; + + + public NameFormatterPreferences(List nameFormatterKey, List nameFormatterValue) { + this.nameFormatterKey = nameFormatterKey; + this.nameFormatterValue = nameFormatterValue; + } + + public static NameFormatterPreferences fromPreferences(JabRefPreferences jabRefPreferences) { + return new NameFormatterPreferences(jabRefPreferences.getStringList(NameFormatter.NAME_FORMATER_KEY), + jabRefPreferences.getStringList(NameFormatter.NAME_FORMATTER_VALUE)); + } + + public List getNameFormatterKey() { + return nameFormatterKey; + } + + + public List getNameFormatterValue() { + return nameFormatterValue; + } +} diff --git a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java index 592ca3b4ec56..fa4eae9fdd08 100644 --- a/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java +++ b/src/main/java/net/sf/jabref/logic/layout/format/WrapFileLinks.java @@ -18,19 +18,15 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import net.sf.jabref.Globals; import net.sf.jabref.logic.layout.AbstractParamLayoutFormatter; import net.sf.jabref.logic.util.io.FileUtil; -import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -118,7 +114,7 @@ public class WrapFileLinks extends AbstractParamLayoutFormatter { // Define which escape sequences give what results: private static final Map ESCAPE_SEQ = new HashMap<>(); - private final JabRefPreferences prefs; + private final FileLinkPreferences prefs; static { WrapFileLinks.ESCAPE_SEQ.put('i', WrapFileLinks.ITERATION_COUNT); @@ -130,8 +126,8 @@ public class WrapFileLinks extends AbstractParamLayoutFormatter { } - public WrapFileLinks(JabRefPreferences prefs) { - this.prefs = prefs; + public WrapFileLinks(FileLinkPreferences fileLinkPreferences) { + this.prefs = fileLinkPreferences; } @Override @@ -178,10 +174,10 @@ public String format(String field) { // but that is not available from a formatter. Therefore, as an // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: - if (prefs.fileDirForDatabase == null) { - dirs = Collections.singletonList(prefs.get(FieldName.FILE + Globals.DIR_SUFFIX)); + if (prefs.getFileDirForDatabase() == null) { + dirs = prefs.getGeneratedDirForDatabase(); } else { - dirs = prefs.fileDirForDatabase; + dirs = prefs.getFileDirForDatabase(); } Optional f = FileUtil.expandFilename(flEntry.getLink(), dirs); diff --git a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java index 488d1412042c..8b9d0b5a62ab 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/OOBibStyle.java @@ -36,9 +36,9 @@ import java.util.TreeSet; import java.util.regex.Pattern; -import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; import net.sf.jabref.logic.layout.LayoutFormatter; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.model.database.BibDatabase; @@ -46,7 +46,6 @@ import net.sf.jabref.model.entry.AuthorList; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -147,16 +146,14 @@ enum BibStyleMode { private static final String AUTHOR_LAST_SEPARATOR = "AuthorLastSeparator"; private static final String AUTHOR_SEPARATOR = "AuthorSeparator"; - private final JournalAbbreviationLoader repositoryLoader; - private final JabRefPreferences prefs; + private final LayoutFormatterPreferences prefs; private static final Pattern QUOTED = Pattern.compile("\".*\""); private static final Log LOGGER = LogFactory.getLog(OOBibStyle.class); - public OOBibStyle(File styleFile, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader, + public OOBibStyle(File styleFile, LayoutFormatterPreferences prefs, Charset encoding) throws IOException { - this.repositoryLoader = Objects.requireNonNull(repositoryLoader); this.prefs = Objects.requireNonNull(prefs); this.styleFile = Objects.requireNonNull(styleFile); this.encoding = Objects.requireNonNull(encoding); @@ -166,9 +163,8 @@ public OOBibStyle(File styleFile, JabRefPreferences prefs, JournalAbbreviationLo path = styleFile.getPath(); } - public OOBibStyle(String resourcePath, JabRefPreferences prefs, JournalAbbreviationLoader repositoryLoader) + public OOBibStyle(String resourcePath, LayoutFormatterPreferences prefs) throws IOException { - this.repositoryLoader = Objects.requireNonNull(repositoryLoader); this.prefs = Objects.requireNonNull(prefs); this.encoding = StandardCharsets.UTF_8; setDefaultProperties(); @@ -383,8 +379,7 @@ private void handleStructureLine(String line) { boolean setDefault = line.substring(0, index).equals(OOBibStyle.DEFAULT_MARK); String type = line.substring(0, index); try { - Layout layout = new LayoutHelper(new StringReader(formatString), this.prefs, this.repositoryLoader) - .getLayoutFromText(); + Layout layout = new LayoutHelper(new StringReader(formatString), this.prefs).getLayoutFromText(); if (setDefault) { defaultBibLayout = layout; } else { diff --git a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java index 1d0d1f5761a8..578d6af288a5 100644 --- a/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java +++ b/src/main/java/net/sf/jabref/logic/openoffice/StyleLoader.java @@ -24,8 +24,7 @@ import java.util.List; import java.util.Objects; -import net.sf.jabref.logic.journals.JournalAbbreviationLoader; -import net.sf.jabref.preferences.JabRefPreferences; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -41,10 +40,9 @@ public class StyleLoader { private final List internalStyleFiles = Arrays.asList(DEFAULT_AUTHORYEAR_STYLE_PATH, DEFAULT_NUMERICAL_STYLE_PATH); - private final JournalAbbreviationLoader journalAbbreviationLoader; private final OpenOfficePreferences preferences; private final Charset encoding; - private final JabRefPreferences jabrefPreferences; + private final LayoutFormatterPreferences layoutFormatterPreferences; // Lists of the internal // and external styles @@ -52,11 +50,10 @@ public class StyleLoader { private final List externalStyles = new ArrayList<>(); - public StyleLoader(OpenOfficePreferences preferences, JabRefPreferences jabrefPreferences, - JournalAbbreviationLoader journalAbbreviationLoader, Charset encoding) { - this.journalAbbreviationLoader = Objects.requireNonNull(journalAbbreviationLoader); + public StyleLoader(OpenOfficePreferences preferences, LayoutFormatterPreferences jabrefPreferences, + Charset encoding) { this.preferences = Objects.requireNonNull(preferences); - this.jabrefPreferences = Objects.requireNonNull(jabrefPreferences); + this.layoutFormatterPreferences = Objects.requireNonNull(jabrefPreferences); this.encoding = Objects.requireNonNull(encoding); loadInternalStyles(); loadExternalStyles(); @@ -76,8 +73,7 @@ public List getStyles() { public boolean addStyleIfValid(String filename) { Objects.requireNonNull(filename); try { - OOBibStyle newStyle = new OOBibStyle(new File(filename), jabrefPreferences, journalAbbreviationLoader, - encoding); + OOBibStyle newStyle = new OOBibStyle(new File(filename), layoutFormatterPreferences, encoding); if (externalStyles.contains(newStyle)) { LOGGER.info("External style file " + filename + " already existing."); } else if (newStyle.isValid()) { @@ -103,8 +99,7 @@ private void loadExternalStyles() { List lists = preferences.getExternalStyles(); for (String filename : lists) { try { - OOBibStyle style = new OOBibStyle(new File(filename), jabrefPreferences, journalAbbreviationLoader, - encoding); + OOBibStyle style = new OOBibStyle(new File(filename), layoutFormatterPreferences, encoding); if (style.isValid()) { //Problem! externalStyles.add(style); } else { @@ -123,7 +118,7 @@ private void loadInternalStyles() { internalStyles.clear(); for (String filename : internalStyleFiles) { try { - internalStyles.add(new OOBibStyle(filename, jabrefPreferences, journalAbbreviationLoader)); + internalStyles.add(new OOBibStyle(filename, layoutFormatterPreferences)); } catch (IOException e) { LOGGER.info("Problem reading internal style file " + filename, e); } 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 550ef8e8f302..b8d8a4b05277 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 @@ -39,6 +39,7 @@ import net.sf.jabref.BibDatabaseContext; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.logic.layout.LayoutHelper; import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.database.BibDatabase; @@ -398,7 +399,8 @@ public static String createFileNameFromPattern(BibDatabase database, BibEntry en StringReader sr = new StringReader(prefs.get(JabRefPreferences.PREF_IMPORT_FILENAMEPATTERN)); Layout layout = null; try { - layout = new LayoutHelper(sr, prefs, repositoryLoader).getLayoutFromText(); + layout = new LayoutHelper(sr, LayoutFormatterPreferences.fromPreferences(prefs, repositoryLoader)) + .getLayoutFromText(); } catch (IOException e) { LOGGER.info("Wrong format " + e.getMessage(), e); } diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java index 467bbf64ecd8..a791adfce2ba 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutEntryTest.java @@ -86,7 +86,9 @@ public void setUp() { public String layout(String layoutFile, BibEntry entry, Optional highlightPattern) throws IOException { StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); - Layout layout = new LayoutHelper(sr, Globals.prefs, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); + Layout layout = new LayoutHelper(sr, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))) + .getLayoutFromText(); return layout.doLayout(entry, null, highlightPattern); } diff --git a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java index e045a7eff4dc..5d5e8cdf1962 100644 --- a/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/LayoutTest.java @@ -53,7 +53,9 @@ public String layout(String layoutFile, String entry) throws IOException { BibEntry be = LayoutTest.bibtexString2BibtexEntry(entry); StringReader sr = new StringReader(layoutFile.replace("__NEWLINE__", "\n")); - Layout layout = new LayoutHelper(sr, Globals.prefs, mock(JournalAbbreviationLoader.class)).getLayoutFromText(); + Layout layout = new LayoutHelper(sr, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))) + .getLayoutFromText(); return layout.doLayout(be, null); } diff --git a/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java b/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java index df66e221d17d..bf173f5f0cf1 100644 --- a/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java +++ b/src/test/java/net/sf/jabref/logic/layout/format/FileLinkTest.java @@ -21,40 +21,41 @@ public void setUp() throws Exception { @Test public void testEmpty() { - assertEquals("", new FileLink(Globals.prefs).format("")); + assertEquals("", new FileLink(FileLinkPreferences.fromPreferences(Globals.prefs)).format("")); } @Test public void testNull() { - assertEquals("", new FileLink(Globals.prefs).format(null)); + assertEquals("", new FileLink(FileLinkPreferences.fromPreferences(Globals.prefs)).format(null)); } @Test public void testOnlyFilename() { - assertEquals("test.pdf", new FileLink(Globals.prefs).format("test.pdf")); + assertEquals("test.pdf", new FileLink(FileLinkPreferences.fromPreferences(Globals.prefs)).format("test.pdf")); } @Test public void testCompleteRecord() { - assertEquals("test.pdf", new FileLink(Globals.prefs).format("paper:test.pdf:PDF")); + assertEquals("test.pdf", + new FileLink(FileLinkPreferences.fromPreferences(Globals.prefs)).format("paper:test.pdf:PDF")); } @Test public void testMultipleFiles() { - ParamLayoutFormatter a = new FileLink(Globals.prefs); + ParamLayoutFormatter a = new FileLink(FileLinkPreferences.fromPreferences(Globals.prefs)); assertEquals("test.pdf", a.format("paper:test.pdf:PDF;presentation:pres.ppt:PPT")); } @Test public void testMultipleFilesPick() { - ParamLayoutFormatter a = new FileLink(Globals.prefs); + ParamLayoutFormatter a = new FileLink(FileLinkPreferences.fromPreferences(Globals.prefs)); a.setArgument("ppt"); assertEquals("pres.ppt", a.format("paper:test.pdf:PDF;presentation:pres.ppt:PPT")); } @Test public void testMultipleFilesPickNonExistant() { - ParamLayoutFormatter a = new FileLink(Globals.prefs); + ParamLayoutFormatter a = new FileLink(FileLinkPreferences.fromPreferences(Globals.prefs)); a.setArgument("doc"); assertEquals("", a.format("paper:test.pdf:PDF;presentation:pres.ppt:PPT")); } diff --git a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java index 5e39f3981ea9..f42a0d692d4b 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/OOBibStyleTest.java @@ -20,6 +20,7 @@ import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.layout.Layout; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.preferences.JabRefPreferences; @@ -49,8 +50,8 @@ public void tearDown() { @Test public void testAuthorYear() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertTrue(style.isValid()); assertTrue(style.isFromResource()); assertFalse(style.isBibtexKeyCiteMarkers()); @@ -67,7 +68,8 @@ public void testAuthorYearAsFile() throws URISyntaxException, IOException { File defFile = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile(); - OOBibStyle style = new OOBibStyle(defFile, Globals.prefs, mock(JournalAbbreviationLoader.class), + OOBibStyle style = new OOBibStyle(defFile, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), Globals.prefs.getDefaultEncoding()); assertTrue(style.isValid()); assertFalse(style.isFromResource()); @@ -82,8 +84,8 @@ public void testAuthorYearAsFile() throws URISyntaxException, IOException { @Test public void testNumerical() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertTrue(style.isValid()); assertFalse(style.isBibtexKeyCiteMarkers()); assertFalse(style.isBoldCitations()); @@ -96,8 +98,8 @@ public void testNumerical() throws IOException { @Test public void testGetNumCitationMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertEquals("[1] ", style.getNumCitationMarker(Arrays.asList(1), -1, true)); assertEquals("[1]", style.getNumCitationMarker(Arrays.asList(1), -1, false)); assertEquals("[1] ", style.getNumCitationMarker(Arrays.asList(1), 0, true)); @@ -113,8 +115,8 @@ public void testGetNumCitationMarker() throws IOException { @Test public void testGetNumCitationMarkerUndefined() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "; 2-4] ", style.getNumCitationMarker(Arrays.asList(4, 2, 3, 0), 1, true)); @@ -131,8 +133,8 @@ public void testGetNumCitationMarkerUndefined() throws IOException { @Test public void testGetCitProperty() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertEquals(", ", style.getStringCitProperty("AuthorSeparator")); assertEquals(3, style.getIntCitProperty("MaxAuthors")); assertTrue(style.getBooleanCitProperty(OOBibStyle.MULTI_CITE_CHRONOLOGICAL)); @@ -146,8 +148,8 @@ public void testGetCitProperty() throws IOException { public void testGetCitationMarker() throws IOException { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); BibDatabase db = result.getDatabase(); for (BibEntry entry : db.getEntries()) { @@ -167,8 +169,8 @@ public void testGetCitationMarker() throws IOException { public void testLayout() throws IOException { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); ParserResult result = BibtexParser.parse(ImportFormat.getReader(testBibtexFile, StandardCharsets.UTF_8)); - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); BibDatabase db = result.getDatabase(); Layout l = style.getReferenceFormat("default"); @@ -187,8 +189,8 @@ public void testLayout() throws IOException { @Test public void testInstitutionAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); BibDatabase database = new BibDatabase(); Layout l = style.getReferenceFormat("article"); @@ -206,8 +208,8 @@ public void testInstitutionAuthor() throws IOException { @Test public void testVonAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); BibDatabase database = new BibDatabase(); Layout l = style.getReferenceFormat("article"); @@ -225,8 +227,8 @@ public void testVonAuthor() throws IOException { @Test public void testInstitutionAuthorMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -245,8 +247,8 @@ public void testInstitutionAuthorMarker() throws IOException { @Test public void testVonAuthorMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -265,8 +267,8 @@ public void testVonAuthorMarker() throws IOException { @Test public void testNullAuthorMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -283,8 +285,8 @@ public void testNullAuthorMarker() throws IOException { @Test public void testNullYearMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -301,8 +303,8 @@ public void testNullYearMarker() throws IOException { @Test public void testEmptyEntryMarker() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -318,8 +320,8 @@ public void testEmptyEntryMarker() throws IOException { @Test public void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -354,8 +356,8 @@ public void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { @Test public void testGetCitationMarkerInTextUniquefiers() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -390,8 +392,8 @@ public void testGetCitationMarkerInTextUniquefiers() throws IOException { @Test public void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -425,8 +427,8 @@ public void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throw @Test public void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOException { - OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); @@ -461,38 +463,38 @@ public void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOExc @Test // TODO: equals only work when initialized from file, not from reader public void testEquals() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertEquals(style1, style2); } @Test // TODO: equals only work when initialized from file, not from reader public void testNotEquals() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertNotEquals(style1, style2); } @Test public void testCompareToEqual() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertEquals(0, style1.compareTo(style2)); } @Test public void testCompareToNotEqual() throws IOException { - OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); - OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, Globals.prefs, - mock(JournalAbbreviationLoader.class)); + OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); + OOBibStyle style2 = new OOBibStyle(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); assertTrue(style1.compareTo(style2) > 0); assertFalse(style2.compareTo(style1) > 0); } @@ -501,7 +503,8 @@ public void testCompareToNotEqual() throws IOException { @Ignore public void testEmptyStringPropertyAndOxfordComma() throws URISyntaxException, IOException { String fileName = Paths.get(OOBibStyleTest.class.getResource("test.jstyle").toURI()).toString(); - OOBibStyle style = new OOBibStyle(fileName, Globals.prefs, mock(JournalAbbreviationLoader.class)); + OOBibStyle style = new OOBibStyle(fileName, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class))); Map entryDBMap = new HashMap<>(); List entries = new ArrayList<>(); BibDatabase database = new BibDatabase(); diff --git a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java index 7aa754418396..6e53aafe18e9 100644 --- a/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java +++ b/src/test/java/net/sf/jabref/logic/openoffice/StyleLoaderTest.java @@ -10,6 +10,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefMain; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.logic.layout.LayoutFormatterPreferences; import net.sf.jabref.preferences.JabRefPreferences; import org.junit.After; @@ -48,30 +49,32 @@ public void tearDown() throws Exception { @Test(expected = NullPointerException.class) public void throwNPEWithNullPreferences() { - loader = new StyleLoader(null, Globals.prefs, - mock(JournalAbbreviationLoader.class), mock(Charset.class)); + loader = new StyleLoader(null, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + mock(Charset.class)); fail(); } @Test(expected = NullPointerException.class) public void throwNPEWithNullRepository() { - loader = new StyleLoader(mock(OpenOfficePreferences.class), Globals.prefs, - null, mock(Charset.class)); + loader = new StyleLoader(mock(OpenOfficePreferences.class), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, null), mock(Charset.class)); fail(); } @Test(expected = NullPointerException.class) public void throwNPEWithNullCharset() { - loader = new StyleLoader(mock(OpenOfficePreferences.class), Globals.prefs, - mock(JournalAbbreviationLoader.class), null); + loader = new StyleLoader(mock(OpenOfficePreferences.class), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), null); fail(); } @Test public void testGetStylesWithEmptyExternal() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(preferences, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); assertEquals(2, loader.getStyles().size()); } @@ -79,8 +82,9 @@ public void testGetStylesWithEmptyExternal() { @Test public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(preferences, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); @@ -92,8 +96,9 @@ public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { public void testAddInvalidStyleLeadsToNoMoreStyle() { preferences.setExternalStyles(Collections.emptyList()); Globals.prefs.putStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES, Collections.emptyList()); - loader = new StyleLoader(preferences, Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(preferences, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); int beforeAdding = loader.getStyles().size(); loader.addStyleIfValid("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky"); assertEquals(beforeAdding, loader.getStyles().size()); @@ -104,8 +109,9 @@ public void testInitalizeWithOneExternalFile() throws URISyntaxException { String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); preferences.setExternalStyles(Collections.singletonList(filename)); - loader = new StyleLoader(preferences, Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(preferences, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); assertEquals(numberOfInternalStyles + 1, loader.getStyles().size()); } @@ -113,8 +119,9 @@ public void testInitalizeWithOneExternalFile() throws URISyntaxException { public void testInitalizeWithIncorrectExternalFile() { preferences.setExternalStyles(Collections.singletonList("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky")); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); assertEquals(numberOfInternalStyles, loader.getStyles().size()); } @@ -124,8 +131,9 @@ public void testInitalizeWithOneExternalFileRemoveStyle() throws URISyntaxExcept .toFile().getPath(); preferences.setExternalStyles(Collections.singletonList(filename)); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); int beforeRemoving = loader.getStyles().size(); for (OOBibStyle style : loader.getStyles()) { @@ -146,8 +154,9 @@ public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() thro .toFile().getPath(); preferences.setExternalStyles(Collections.singletonList(filename)); - loader = new StyleLoader(preferences, Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(preferences, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { if (!style.isFromResource()) { @@ -164,8 +173,9 @@ public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() thro @Test public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); int beforeAdding = loader.getStyles().size(); String filename = Paths.get(JabRefMain.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); @@ -176,8 +186,9 @@ public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException @Test(expected = NullPointerException.class) public void testAddNullStyleThrowsNPE() { - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); loader.addStyleIfValid(null); fail(); } @@ -186,8 +197,9 @@ public void testAddNullStyleThrowsNPE() { @Test public void testGetDefaultUsedStyleWhenEmpty() { Globals.prefs.remove(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, style.getPath()); @@ -197,8 +209,9 @@ public void testGetDefaultUsedStyleWhenEmpty() { @Test public void testGetStoredUsedStyle() { preferences.setCurrentStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, style.getPath()); @@ -208,8 +221,9 @@ public void testGetStoredUsedStyle() { @Test public void testGtDefaultUsedStyleWhenIncorrect() { preferences.setCurrentStyle("ljlkjlkjnljnvdlsjniuhwelfhuewfhlkuewhfuwhelu"); - loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), Globals.prefs, - mock(JournalAbbreviationLoader.class), Globals.prefs.getDefaultEncoding()); + loader = new StyleLoader(new OpenOfficePreferences(Globals.prefs), + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), + Globals.prefs.getDefaultEncoding()); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, style.getPath()); @@ -220,7 +234,8 @@ public void testGtDefaultUsedStyleWhenIncorrect() { public void testRemoveInternalStyleReturnsFalseAndDoNotRemove() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, Globals.prefs, mock(JournalAbbreviationLoader.class), + loader = new StyleLoader(preferences, + LayoutFormatterPreferences.fromPreferences(Globals.prefs, mock(JournalAbbreviationLoader.class)), Globals.prefs.getDefaultEncoding()); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { From dada76f8ea29caaf443c512df8fbc33948d15208 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 23 Jul 2016 11:50:40 +0200 Subject: [PATCH 264/268] Added more fields and fixed some issues (#1617) --- .../sf/jabref/external/WriteXMPAction.java | 2 +- .../external/WriteXMPEntryEditorAction.java | 2 +- .../java/net/sf/jabref/gui/BasePanel.java | 8 +- .../jabref/gui/FindUnlinkedFilesDialog.java | 3 +- .../java/net/sf/jabref/gui/GUIGlobals.java | 6 +- .../sf/jabref/gui/desktop/JabRefDesktop.java | 16 +- .../jabref/gui/maintable/MainTableFormat.java | 2 +- .../net/sf/jabref/importer/OAI2Handler.java | 2 +- .../fileformat/BiblioscapeImporter.java | 6 +- .../importer/fileformat/FreeCiteImporter.java | 2 +- .../jabref/logic/cleanup/CleanupWorker.java | 3 +- .../jabref/logic/exporter/OOCalcDatabase.java | 4 +- .../exporter/OpenDocumentRepresentation.java | 4 +- .../sf/jabref/logic/msbib/MSBibMapping.java | 2 +- .../java/net/sf/jabref/logic/xmp/XMPUtil.java | 8 +- .../migrations/FileLinksUpgradeWarning.java | 2 +- .../model/entry/BibLatexEntryTypes.java | 192 ++++++++++-------- .../jabref/model/entry/BibtexEntryTypes.java | 2 +- .../sf/jabref/model/entry/EntryConverter.java | 12 +- .../net/sf/jabref/model/entry/FieldName.java | 11 + .../model/entry/InternalBibtexFields.java | 12 +- 21 files changed, 169 insertions(+), 132 deletions(-) diff --git a/src/main/java/net/sf/jabref/external/WriteXMPAction.java b/src/main/java/net/sf/jabref/external/WriteXMPAction.java index d69fb185fe09..87b2692a62db 100644 --- a/src/main/java/net/sf/jabref/external/WriteXMPAction.java +++ b/src/main/java/net/sf/jabref/external/WriteXMPAction.java @@ -134,7 +134,7 @@ public void run() { List files = new ArrayList<>(); // First check the (legacy) "pdf" field: - entry.getFieldOptional("pdf").ifPresent(pdf -> + entry.getFieldOptional(FieldName.PDF).ifPresent(pdf -> FileUtil.expandFilename(pdf, panel.getBibDatabaseContext().getFileDirectory("pdf")) .ifPresent(files::add)); // Then check the "file" field: diff --git a/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java b/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java index d4366c247066..bdb4f8867635 100644 --- a/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java +++ b/src/main/java/net/sf/jabref/external/WriteXMPEntryEditorAction.java @@ -68,7 +68,7 @@ public void actionPerformed(ActionEvent actionEvent) { List files = new ArrayList<>(); // First check the (legacy) "pdf" field: - entry.getFieldOptional("pdf").ifPresent(pdf -> FileUtil + entry.getFieldOptional(FieldName.PDF).ifPresent(pdf -> FileUtil .expandFilename(pdf, panel.getBibDatabaseContext().getFileDirectory("pdf")).ifPresent(files::add)); // Then check the "file" field: diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index 75e4616323e2..b8368ce3d799 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -2059,10 +2059,6 @@ public void action() { private class OpenURLAction implements BaseAction { - private static final String PS_FIELD = "ps"; - private static final String PDF_FIELD = "pdf"; - - @Override public void action() { final List bes = mainTable.getSelectedEntries(); @@ -2089,8 +2085,8 @@ public void action() { for (int i = 0; i < tm.getRowCount(); i++) { FileListEntry flEntry = tm.getEntry(i); if (FieldName.URL.equalsIgnoreCase(flEntry.type.get().getName()) - || PS_FIELD.equalsIgnoreCase(flEntry.type.get().getName()) - || PDF_FIELD.equalsIgnoreCase(flEntry.type.get().getName())) { + || FieldName.PS.equalsIgnoreCase(flEntry.type.get().getName()) + || FieldName.PDF.equalsIgnoreCase(flEntry.type.get().getName())) { entry = flEntry; break; } diff --git a/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java b/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java index f67e3b666ba7..7fa6a10d674f 100644 --- a/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java +++ b/src/main/java/net/sf/jabref/gui/FindUnlinkedFilesDialog.java @@ -91,6 +91,7 @@ import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.EntryType; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; @@ -997,7 +998,7 @@ public void mousePressed(MouseEvent e) { try { JabRefDesktop.openExternalViewer( JabRefGUI.getMainFrame().getCurrentBasePanel().getBibDatabaseContext(), - fnw.file.getAbsolutePath(), "pdf"); + fnw.file.getAbsolutePath(), FieldName.PDF); } catch (IOException e1) { LOGGER.info("Error opening file", e1); } diff --git a/src/main/java/net/sf/jabref/gui/GUIGlobals.java b/src/main/java/net/sf/jabref/gui/GUIGlobals.java index 8f1ed9552bcb..1266eef414f5 100644 --- a/src/main/java/net/sf/jabref/gui/GUIGlobals.java +++ b/src/main/java/net/sf/jabref/gui/GUIGlobals.java @@ -97,7 +97,7 @@ public static void init() { JLabel label; label = new JLabel(IconTheme.JabRefIcon.PDF_FILE.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " PDF"); - GUIGlobals.TABLE_ICONS.put("pdf", label); + GUIGlobals.TABLE_ICONS.put(FieldName.PDF, label); label = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " URL"); @@ -109,7 +109,7 @@ public static void init() { label = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " ArXiv URL"); - GUIGlobals.TABLE_ICONS.put("eprint", label); + GUIGlobals.TABLE_ICONS.put(FieldName.EPRINT, label); label = new JLabel(IconTheme.JabRefIcon.DOI.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " DOI " + Localization.lang("web link")); @@ -117,7 +117,7 @@ public static void init() { label = new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon()); label.setToolTipText(Localization.lang("Open") + " PS"); - GUIGlobals.TABLE_ICONS.put("ps", label); + GUIGlobals.TABLE_ICONS.put(FieldName.PS, label); label = new JLabel(IconTheme.JabRefIcon.FOLDER.getSmallIcon()); label.setToolTipText(Localization.lang("Open folder")); diff --git a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java index 338a3cd4038a..f1fbd1eb11f3 100644 --- a/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/net/sf/jabref/gui/desktop/JabRefDesktop.java @@ -74,7 +74,7 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, String String initialFieldName) throws IOException { String link = initialLink; String fieldName = initialFieldName; - if ("ps".equals(fieldName) || "pdf".equals(fieldName)) { + if (FieldName.PS.equals(fieldName) || FieldName.PDF.equals(fieldName)) { // Find the default directory for this field type: List dir = databaseContext.getFileDirectory(fieldName); @@ -90,10 +90,10 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, String String[] split = file.get().getName().split("\\."); if (split.length >= 2) { if ("pdf".equalsIgnoreCase(split[split.length - 1])) { - fieldName = "pdf"; + fieldName = FieldName.PDF; } else if ("ps".equalsIgnoreCase(split[split.length - 1]) || ((split.length >= 3) && "ps".equalsIgnoreCase(split[split.length - 2]))) { - fieldName = "ps"; + fieldName = FieldName.PS; } } } else if (FieldName.DOI.equals(fieldName)) { @@ -103,7 +103,7 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, String } // should be opened in browser fieldName = FieldName.URL; - } else if ("eprint".equals(fieldName)) { + } else if (FieldName.EPRINT.equals(fieldName)) { fieldName = FieldName.URL; // Check to see if link field already contains a well formated URL @@ -121,15 +121,15 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, String // In BasePanel.java, the exception is catched and a text output to the frame // throw e; } - } else if ("ps".equals(fieldName)) { + } else if (FieldName.PS.equals(fieldName)) { try { - NATIVE_DESKTOP.openFile(link, "ps"); + NATIVE_DESKTOP.openFile(link, FieldName.PS); } catch (IOException e) { LOGGER.error("An error occured on the command: " + link, e); } - } else if ("pdf".equals(fieldName)) { + } else if (FieldName.PDF.equals(fieldName)) { try { - NATIVE_DESKTOP.openFile(link, "pdf"); + NATIVE_DESKTOP.openFile(link, FieldName.PDF); } catch (IOException e) { LOGGER.error("An error occured on the command: " + link, e); } diff --git a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java index 92105340a819..eafcd39bc61d 100644 --- a/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java +++ b/src/main/java/net/sf/jabref/gui/maintable/MainTableFormat.java @@ -41,7 +41,7 @@ public class MainTableFormat implements TableFormat { // These values are also used to put a heading into the table; see getColumnName(int) private static final List URL_FIRST = Arrays.asList(FieldName.URL, FieldName.DOI); private static final List DOI_FIRST = Arrays.asList(FieldName.DOI, FieldName.URL); - private static final List ARXIV = Collections.singletonList("eprint"); + private static final List ARXIV = Collections.singletonList(FieldName.EPRINT); private final BibDatabase database; diff --git a/src/main/java/net/sf/jabref/importer/OAI2Handler.java b/src/main/java/net/sf/jabref/importer/OAI2Handler.java index c46dfbf65313..c292bc108821 100644 --- a/src/main/java/net/sf/jabref/importer/OAI2Handler.java +++ b/src/main/java/net/sf/jabref/importer/OAI2Handler.java @@ -73,7 +73,7 @@ public void endElement(String uri, String localName, String qualifiedName) throw if ("error".equals(qualifiedName)) { throw new RuntimeException(content); } else if ("id".equals(qualifiedName)) { - entry.setField("eprint", content); + entry.setField(FieldName.EPRINT, content); } else if ("keyname".equals(qualifiedName)) { keyname = content; } else if ("forenames".equals(qualifiedName)) { diff --git a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java index e125210f8fc5..35a9002abb7c 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/BiblioscapeImporter.java @@ -160,7 +160,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { } else if ("UR".equals(entry.getKey()) || "AT".equals(entry.getKey())) { String s = entry.getValue().toString().trim(); hm.put(s.startsWith("http://") || s.startsWith("ftp://") ? FieldName.URL - : "pdf", entry.getValue().toString()); + : FieldName.PDF, entry.getValue().toString()); } else if ("C1".equals(entry.getKey())) { comments.add("Custom1: " + entry.getValue()); @@ -180,7 +180,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { comments.add("Custom6: " + entry.getValue()); } else if ("DE".equals(entry.getKey())) { - hm.put("annote", entry + hm.put(FieldName.ANNOTE, entry .getValue().toString()); } else if ("CA".equals(entry.getKey())) { comments.add("Categories: " @@ -190,7 +190,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException { + entry.getValue()); } else if ("SE".equals(entry.getKey())) { - hm.put("chapter", entry + hm.put(FieldName.CHAPTER, entry .getValue().toString()); //else if (entry.getKey().equals("AC")) // hm.put("",entry.getValue().toString()); diff --git a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java index 83a1fdde592a..050ede299dd4 100644 --- a/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java +++ b/src/main/java/net/sf/jabref/importer/fileformat/FreeCiteImporter.java @@ -168,7 +168,7 @@ public ParserResult importEntries(String text) { e.setField(FieldName.NUMBER, parser.getElementText()); } else if (FieldName.DOI.equals(ln) || FieldName.INSTITUTION.equals(ln) - || "location".equals(ln) + || FieldName.LOCATION.equals(ln) || FieldName.NUMBER.equals(ln) || FieldName.NOTE.equals(ln) || FieldName.TITLE.equals(ln) diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java index f604eca8c865..3c6da685d6f4 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java @@ -23,6 +23,7 @@ import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.preferences.JabRefPreferences; public class CleanupWorker { @@ -62,7 +63,7 @@ private List determineCleanupActions(CleanupPreset preset) { List jobs = new ArrayList<>(); if (preset.isCleanUpUpgradeExternalLinks()) { - jobs.add(new UpgradePdfPsToFileCleanup(Arrays.asList("pdf", "ps"))); + jobs.add(new UpgradePdfPsToFileCleanup(Arrays.asList(FieldName.PDF, FieldName.PS))); } if (preset.isCleanUpDOI()) { jobs.add(new DoiCleanup()); diff --git a/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java index 545c431bbdfe..6869052b6716 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OOCalcDatabase.java @@ -170,7 +170,7 @@ public Document getDOMrepresentation() { addTableCell(result, row, getField(e, FieldName.NOTE)); addTableCell(result, row, getField(e, FieldName.URL)); addTableCell(result, row, getField(e, FieldName.BOOKTITLE)); - addTableCell(result, row, getField(e, "chapter")); + addTableCell(result, row, getField(e, FieldName.CHAPTER)); addTableCell(result, row, getField(e, FieldName.EDITION)); addTableCell(result, row, getField(e, FieldName.SERIES)); addTableCell(result, row, getField(e, FieldName.EDITOR));//new AuthorLastFirst().format(getField(e, FieldName.EDITOR_FIELD))); @@ -180,7 +180,7 @@ public Document getDOMrepresentation() { addTableCell(result, row, getField(e, FieldName.INSTITUTION)); addTableCell(result, row, getField(e, FieldName.ORGANIZATION)); addTableCell(result, row, getField(e, FieldName.SCHOOL)); - addTableCell(result, row, getField(e, "annote")); + addTableCell(result, row, getField(e, FieldName.ANNOTE)); addTableCell(result, row, getField(e, "assignee")); addTableCell(result, row, getField(e, "day")); addTableCell(result, row, getField(e, "dayfiled")); diff --git a/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java index e075d095c578..4f1071522840 100644 --- a/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java +++ b/src/main/java/net/sf/jabref/logic/exporter/OpenDocumentRepresentation.java @@ -164,10 +164,10 @@ public Document getDOMrepresentation() { addTableCell(result, row, new GetOpenOfficeType().format(e.getType())); addTableCell(result, row, getField(e, FieldName.ADDRESS)); addTableCell(result, row, getField(e, "assignee")); - addTableCell(result, row, getField(e, "annote")); + addTableCell(result, row, getField(e, FieldName.ANNOTE)); addTableCell(result, row, getField(e, FieldName.AUTHOR));//new AuthorLastFirst().format(getField(e, FieldName.AUTHOR_FIELD))); addTableCell(result, row, getField(e, FieldName.BOOKTITLE)); - addTableCell(result, row, getField(e, "chapter")); + addTableCell(result, row, getField(e, FieldName.CHAPTER)); addTableCell(result, row, getField(e, "day")); addTableCell(result, row, getField(e, "dayfiled")); addTableCell(result, row, getField(e, FieldName.EDITION)); diff --git a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java index eff6257ee4ef..11f30da029e9 100644 --- a/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java +++ b/src/main/java/net/sf/jabref/logic/msbib/MSBibMapping.java @@ -28,7 +28,7 @@ public class MSBibMapping { bibtexToMSBib.put(FieldName.BOOKTITLE, "BookTitle"); //bibtexToMSBib.put(FieldName.BOOKTITLE, "ConferenceName"); //bibtexToMSBib.put(FieldName.PAGES, "Pages"); - bibtexToMSBib.put("chapter", "ChapterNumber"); + bibtexToMSBib.put(FieldName.CHAPTER, "ChapterNumber"); bibtexToMSBib.put(FieldName.JOURNAL, "JournalName"); bibtexToMSBib.put(FieldName.NUMBER, "Issue"); bibtexToMSBib.put(FieldName.SCHOOL, "Department"); diff --git a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java index c50e16f526b4..8abfc49147ea 100644 --- a/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java +++ b/src/main/java/net/sf/jabref/logic/xmp/XMPUtil.java @@ -376,7 +376,7 @@ public static Optional getBibtexEntryFromDublinCore(XMPSchemaDublinCor */ List publishers = dcSchema.getPublishers(); if ((publishers != null) && !publishers.isEmpty()) { - entry.setField("publishers", String.join(" and ", publishers)); + entry.setField(FieldName.PUBLISHER, String.join(" and ", publishers)); } /** @@ -667,7 +667,7 @@ private static void writeToDCSchema(XMPSchemaDublinCore dcSchema, * * Bibtex-Fields used: author */ - if ("author".equals(field)) { + if (FieldName.AUTHOR.equals(field)) { String authors = resolvedEntry.getField(field); AuthorList list = AuthorList.parse(authors); @@ -1009,7 +1009,7 @@ private static void writeDocumentInformation(PDDocument document, if (useXmpPrivacyFilter && filters.contains(field)) { // erase field instead of adding it - if ("author".equals(field)) { + if (FieldName.AUTHOR.equals(field)) { di.setAuthor(null); } else if (FieldName.TITLE.equals(field)) { di.setTitle(null); @@ -1023,7 +1023,7 @@ private static void writeDocumentInformation(PDDocument document, continue; } - if ("author".equals(field)) { + if (FieldName.AUTHOR.equals(field)) { di.setAuthor(resolvedEntry.getField(FieldName.AUTHOR)); } else if (FieldName.TITLE.equals(field)) { di.setTitle(resolvedEntry.getField(FieldName.TITLE)); diff --git a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java index 857b34e934d4..c52f99cec8c8 100644 --- a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java +++ b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java @@ -55,7 +55,7 @@ */ public class FileLinksUpgradeWarning implements PostOpenAction { - private static final String[] FIELDS_TO_LOOK_FOR = new String[] {"pdf", "ps", "evastar_pdf"}; + private static final String[] FIELDS_TO_LOOK_FOR = new String[] {FieldName.PDF, FieldName.PS, "evastar_pdf"}; private boolean offerChangeSettings; diff --git a/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java index 87a04ed9c290..3f855e0ddf59 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/BibLatexEntryTypes.java @@ -30,14 +30,16 @@ public class BibLatexEntryTypes { private final List primaryOptionalFields = Collections.unmodifiableList( Arrays.asList("subtitle", FieldName.EDITOR, FieldName.SERIES, FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.PAGES, - FieldName.NOTE, FieldName.ISSN, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.NOTE, FieldName.ISSN, FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, + FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.JOURNALTITLE, "year/date"); addAllOptional("translator", "annotator", "commentator", "subtitle", "titleaddon", FieldName.EDITOR, "editora", "editorb", "editorc", "journalsubtitle", "issuetitle", "issuesubtitle", FieldName.LANGUAGE, "origlanguage", FieldName.SERIES, FieldName.VOLUME, FieldName.NUMBER, "eid", FieldName.ISSUE, FieldName.MONTH, FieldName.PAGES, "version", FieldName.NOTE, FieldName.ISSN, - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -55,8 +57,9 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", - "mainsubtitle", "maintitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, - "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + "mainsubtitle", "maintitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, + "pagetotal", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE)); { @@ -64,8 +67,9 @@ public List getPrimaryOptionalFields() { addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", FieldName.LANGUAGE, "origlanguage", FieldName.VOLUME, "part", FieldName.EDITION, "volumes", FieldName.SERIES, - FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, "pagetotal", + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -83,14 +87,15 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList(FieldName.EDITOR, "subtitle", "titleaddon", FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "pagetotal", - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", FieldName.LANGUAGE, "origlanguage", - FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "pagetotal", - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.ISBN, "pagetotal", + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -109,7 +114,8 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections.unmodifiableList(Arrays .asList("bookauthor", FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, - "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.CHAPTER, FieldName.PAGES, FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, + FieldName.URL, FieldName.URLDATE)); { @@ -117,9 +123,10 @@ public List getPrimaryOptionalFields() { addAllOptional("bookauthor", FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.LANGUAGE, "origlanguage", - FieldName.VOLUME, "part", FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, - "chapter", FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, - "urldate"); + FieldName.VOLUME, "part", FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.ISBN, + FieldName.CHAPTER, FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, + FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -184,14 +191,16 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType BOOKLET = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, "chapter", - FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, FieldName.CHAPTER, + FieldName.PAGES, FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE)); { addAllRequired("author/editor", FieldName.TITLE, "year/date"); - addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.TYPE, FieldName.NOTE, "location", "chapter", - FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", - FieldName.URL, "urldate"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.TYPE, FieldName.NOTE, FieldName.LOCATION, FieldName.CHAPTER, + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, + FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, + FieldName.URL, FieldName.URLDATE); } @Override @@ -209,8 +218,8 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", "maintitle", - "mainsubtitle", "maintitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + "mainsubtitle", "maintitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { @@ -218,8 +227,8 @@ public List getPrimaryOptionalFields() { addAllOptional("editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", FieldName.LANGUAGE, "origlanguage", FieldName.VOLUME, "part", FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, - FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, - "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.PUBLISHER, FieldName.LOCATION, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, + FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE); } @Override @@ -237,15 +246,15 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("translator", "subtitle", "titleaddon", FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); addAllOptional("editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", FieldName.LANGUAGE, "origlanguage", FieldName.EDITION, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, - FieldName.PUBLISHER, "location", FieldName.ISBN, "pagetotal", "addendum", "pubstate", FieldName.DOI, - "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.PUBLISHER, FieldName.LOCATION, FieldName.ISBN, "pagetotal", "addendum", "pubstate", FieldName.DOI, + FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE); } @Override @@ -264,7 +273,8 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections.unmodifiableList( Arrays.asList("translator", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.VOLUME, FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, - "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.CHAPTER, FieldName.PAGES, FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, + FieldName.URL, FieldName.URLDATE)); { @@ -272,8 +282,9 @@ public List getPrimaryOptionalFields() { addAllOptional(FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", FieldName.LANGUAGE, "origlanguage", FieldName.VOLUME, "part", FieldName.EDITION, - "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -315,14 +326,16 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.EDITION, FieldName.PUBLISHER, FieldName.ISBN, - "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.CHAPTER, FieldName.PAGES, FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, + FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired("author/editor", FieldName.TITLE, "year/date"); addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.EDITION, FieldName.TYPE, FieldName.SERIES, FieldName.NUMBER, "version", - FieldName.NOTE, FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.NOTE, FieldName.ORGANIZATION, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, "pagetotal", + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -339,15 +352,16 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MISC = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, "location", - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, FieldName.LOCATION, + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired("author/editor", FieldName.TITLE, "year/date"); addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.TYPE, "version", FieldName.NOTE, - FieldName.ORGANIZATION, "location", FieldName.MONTH, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", - "eprinttype", FieldName.URL, "urldate"); + FieldName.ORGANIZATION, FieldName.LOCATION, FieldName.MONTH, "addendum", "pubstate", FieldName.DOI, + FieldName.EPRINT, FieldName.EPRINTCLASS, + FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE); } @Override @@ -364,12 +378,12 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType ONLINE = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", FieldName.NOTE, FieldName.ORGANIZATION, "urldate")); + Arrays.asList("subtitle", "titleaddon", FieldName.NOTE, FieldName.ORGANIZATION, FieldName.URLDATE)); { addAllRequired("author/editor", FieldName.TITLE, "year/date", FieldName.URL); - addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, "version", FieldName.NOTE, FieldName.ORGANIZATION, FieldName.MONTH, "addendum", "pubstate", "urldate"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, "version", FieldName.NOTE, FieldName.ORGANIZATION, FieldName.MONTH, "addendum", "pubstate", FieldName.URLDATE); } @Override @@ -386,13 +400,15 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType PATENT = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList(Arrays.asList("holder", - "subtitle", "titleaddon", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + "subtitle", "titleaddon", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE)); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.NUMBER, "year/date"); - addAllOptional("holder", "subtitle", "titleaddon", FieldName.TYPE, "version", "location", FieldName.NOTE, FieldName.MONTH, - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + addAllOptional("holder", "subtitle", "titleaddon", FieldName.TYPE, "version", FieldName.LOCATION, FieldName.NOTE, FieldName.MONTH, + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -410,14 +426,14 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "issuetitle", "issuesubtitle", FieldName.ISSN, FieldName.DOI, - "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.EDITOR, FieldName.TITLE, "year/date"); addAllOptional("editora", "editorb", "editorc", "subtitle", "issuetitle", "issuesubtitle", FieldName.LANGUAGE, FieldName.SERIES, FieldName.VOLUME, FieldName.NUMBER, FieldName.ISSUE, FieldName.MONTH, FieldName.NOTE, FieldName.ISSN, "addendum", "pubstate", - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE); } @Override @@ -459,16 +475,17 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + "maintitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, "pagetotal", + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.TITLE, "year/date"); addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "eventtitle", "eventtitleaddon", "eventdate", "venue", FieldName.LANGUAGE, FieldName.VOLUME, "part", "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, - FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.YEAR, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.ORGANIZATION, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.MONTH, FieldName.YEAR, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, "pagetotal", + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -486,16 +503,17 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "maintitle", "mainsubtitle", - "maintitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, "chapter", FieldName.PAGES, "pagetotal", - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + "maintitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, FieldName.CHAPTER, FieldName.PAGES, "pagetotal", + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.TITLE, "year/date"); addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "eventtitle", "eventtitleaddon", "eventdate", "venue", FieldName.LANGUAGE, "volumes", FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, - FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, "pagetotal", - "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate"); + FieldName.ORGANIZATION, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.MONTH, FieldName.ISBN, "pagetotal", + "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -514,16 +532,18 @@ public List getPrimaryOptionalFields() { private final List primaryOptionalFields = Collections .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", "eventtitle", FieldName.VOLUME, FieldName.PUBLISHER, FieldName.ISBN, - "chapter", FieldName.PAGES, FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + FieldName.CHAPTER, FieldName.PAGES, FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, + FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, "year/date"); addAllOptional(FieldName.EDITOR, "subtitle", "titleaddon", "maintitle", "mainsubtitle", "maintitleaddon", "booksubtitle", "booktitleaddon", "eventtitle", "eventtitleaddon", "eventdate", "venue", FieldName.LANGUAGE, FieldName.VOLUME, "part", "volumes", - FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.ORGANIZATION, FieldName.PUBLISHER, "location", FieldName.MONTH, FieldName.ISBN, - "chapter", FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, - "urldate"); + FieldName.SERIES, FieldName.NUMBER, FieldName.NOTE, FieldName.ORGANIZATION, FieldName.PUBLISHER, FieldName.LOCATION, FieldName.MONTH, FieldName.ISBN, + FieldName.CHAPTER, FieldName.PAGES, "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, + FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -612,15 +632,17 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType REPORT = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.NUMBER, "isrn", "chapter", - FieldName.PAGES, "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.NUMBER, "isrn", FieldName.CHAPTER, + FieldName.PAGES, "pagetotal", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, + FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.TYPE, FieldName.INSTITUTION, "year/date"); - addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NUMBER, "version", FieldName.NOTE, "location", FieldName.MONTH, - "isrn", "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", - "eprintclass", "eprinttype", FieldName.URL, "urldate"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NUMBER, "version", FieldName.NOTE, FieldName.LOCATION, FieldName.MONTH, + "isrn", FieldName.CHAPTER, FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, + FieldName.EPRINT, + FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE); } @Override @@ -648,15 +670,16 @@ public String getName() { public static final BibLatexEntryType THESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", "chapter", FieldName.PAGES, "pagetotal", - FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.CHAPTER, FieldName.PAGES, "pagetotal", + FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.TYPE, FieldName.INSTITUTION, "year/date"); - addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, "location", FieldName.MONTH, FieldName.ISBN, "chapter", - FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, - "urldate"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, FieldName.LOCATION, FieldName.MONTH, FieldName.ISBN, FieldName.CHAPTER, + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, + FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -673,13 +696,13 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType UNPUBLISHED = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, "pubstate", FieldName.URL, "urldate")); + Arrays.asList("subtitle", "titleaddon", FieldName.HOWPUBLISHED, "pubstate", FieldName.URL, FieldName.URLDATE)); { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, "year/date"); - addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.NOTE, "location", FieldName.MONTH, - "addendum", "pubstate", FieldName.URL, "urldate"); + addAllOptional("subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.HOWPUBLISHED, FieldName.NOTE, FieldName.LOCATION, FieldName.MONTH, + "addendum", "pubstate", FieldName.URL, FieldName.URLDATE); } @Override @@ -746,16 +769,18 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType MASTERSTHESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, "chapter", FieldName.PAGES, - "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, FieldName.CHAPTER, FieldName.PAGES, + "pagetotal", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE)); { // Treated as alias of "THESIS", except FieldName.TYPE field is optional addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.INSTITUTION, "year/date"); - addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, "location", FieldName.MONTH, FieldName.ISBN, "chapter", - FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, - "urldate"); + addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, FieldName.LOCATION, FieldName.MONTH, FieldName.ISBN, FieldName.CHAPTER, + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, + FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -772,16 +797,18 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType PHDTHESIS = new BibLatexEntryType() { private final List primaryOptionalFields = Collections - .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, "chapter", FieldName.PAGES, - "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + .unmodifiableList(Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, FieldName.CHAPTER, FieldName.PAGES, + "pagetotal", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE)); { // Treated as alias of "THESIS", except FieldName.TYPE field is optional addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.INSTITUTION, "year/date"); - addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, "location", FieldName.MONTH, FieldName.ISBN, "chapter", - FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, - "urldate"); + addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NOTE, FieldName.LOCATION, FieldName.MONTH, FieldName.ISBN, FieldName.CHAPTER, + FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, FieldName.EPRINT, + FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE); } @Override @@ -798,16 +825,17 @@ public List getPrimaryOptionalFields() { public static final BibLatexEntryType TECHREPORT = new BibLatexEntryType() { private final List primaryOptionalFields = Collections.unmodifiableList( - Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, FieldName.NUMBER, "isrn", "chapter", FieldName.PAGES, - "pagetotal", FieldName.DOI, "eprint", "eprintclass", "eprinttype", FieldName.URL, "urldate")); + Arrays.asList("subtitle", "titleaddon", FieldName.TYPE, FieldName.NUMBER, "isrn", FieldName.CHAPTER, FieldName.PAGES, + "pagetotal", FieldName.DOI, FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, + FieldName.URLDATE)); { // Treated as alias of "REPORT", except FieldName.TYPE field is optional addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.INSTITUTION, "year/date"); - addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NUMBER, "version", FieldName.NOTE, "location", FieldName.MONTH, - "isrn", "chapter", FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, "eprint", - "eprintclass", "eprinttype", FieldName.URL, "urldate"); + addAllOptional(FieldName.TYPE, "subtitle", "titleaddon", FieldName.LANGUAGE, FieldName.NUMBER, "version", FieldName.NOTE, FieldName.LOCATION, FieldName.MONTH, + "isrn", FieldName.CHAPTER, FieldName.PAGES, "pagetotal", "addendum", "pubstate", FieldName.DOI, + FieldName.EPRINT, FieldName.EPRINTCLASS, FieldName.EPRINTTYPE, FieldName.URL, FieldName.URLDATE); } @Override diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java b/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java index 313c54812170..2c490dd787bd 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexEntryTypes.java @@ -116,7 +116,7 @@ public String getName() { { addAllRequired(FieldName.AUTHOR, FieldName.TITLE, FieldName.BOOKTITLE, FieldName.PUBLISHER, FieldName.YEAR); - addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.TYPE, "chapter", FieldName.PAGES, FieldName.ADDRESS, FieldName.EDITION, + addAllOptional(FieldName.EDITOR, FieldName.VOLUME, FieldName.NUMBER, FieldName.SERIES, FieldName.TYPE, FieldName.CHAPTER, FieldName.PAGES, FieldName.ADDRESS, FieldName.EDITION, FieldName.MONTH, FieldName.NOTE); } diff --git a/src/main/java/net/sf/jabref/model/entry/EntryConverter.java b/src/main/java/net/sf/jabref/model/entry/EntryConverter.java index 67bae56b1f4f..21c8e3f6c657 100644 --- a/src/main/java/net/sf/jabref/model/entry/EntryConverter.java +++ b/src/main/java/net/sf/jabref/model/entry/EntryConverter.java @@ -17,13 +17,13 @@ public class EntryConverter { static { EntryConverter.FIELD_ALIASES_TEX_TO_LTX = new HashMap<>(); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.ADDRESS, "location"); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("annote", "annotation"); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("archiveprefix", "eprinttype"); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.ADDRESS, FieldName.LOCATION); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.ANNOTE, FieldName.ANNOTATION); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("archiveprefix", FieldName.EPRINTTYPE); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.JOURNAL, FieldName.JOURNALTITLE); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("key", "sortkey"); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("pdf", FieldName.FILE); - EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("primaryclass", "eprintclass"); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.KEY, "sortkey"); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.PDF, FieldName.FILE); + EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put("primaryclass", FieldName.EPRINTCLASS); EntryConverter.FIELD_ALIASES_TEX_TO_LTX.put(FieldName.SCHOOL, FieldName.INSTITUTION); // inverse map diff --git a/src/main/java/net/sf/jabref/model/entry/FieldName.java b/src/main/java/net/sf/jabref/model/entry/FieldName.java index 0f74b25663f5..bbbd328b6f8b 100644 --- a/src/main/java/net/sf/jabref/model/entry/FieldName.java +++ b/src/main/java/net/sf/jabref/model/entry/FieldName.java @@ -5,13 +5,19 @@ public class FieldName { public static final String ABSTRACT = "abstract"; public static final String ADDRESS = "address"; + public static final String ANNOTE = "annote"; + public static final String ANNOTATION = "annotation"; public static final String AUTHOR = "author"; public static final String BOOKTITLE = "booktitle"; + public static final String CHAPTER = "chapter"; public static final String CROSSREF = "crossref"; public static final String DATE = "date"; public static final String DOI = "doi"; public static final String EDITION = "edition"; public static final String EDITOR = "editor"; + public static final String EPRINT = "eprint"; + public static final String EPRINTCLASS = "eprintclass"; + public static final String EPRINTTYPE = "eprinttype"; public static final String FILE = "file"; public static final String FOLDER = "folder"; public static final String HOWPUBLISHED = "howpublished"; @@ -21,13 +27,17 @@ public class FieldName { public static final String ISSUE = "issue"; public static final String JOURNAL = "journal"; public static final String JOURNALTITLE = "journaltitle"; + public static final String KEY = "key"; public static final String KEYWORDS = "keywords"; public static final String LANGUAGE = "language"; + public static final String LOCATION = "location"; public static final String MONTH = "month"; public static final String NOTE = "note"; public static final String NUMBER = "number"; public static final String ORGANIZATION = "organization"; public static final String PAGES = "pages"; + public static final String PDF = "pdf"; + public static final String PS = "ps"; public static final String PUBLISHER = "publisher"; public static final String REVIEW = "review"; public static final String SCHOOL = "school"; @@ -35,6 +45,7 @@ public class FieldName { public static final String TITLE = "title"; public static final String TYPE = "type"; public static final String URL = "url"; + public static final String URLDATE = "urldate"; public static final String VOLUME = "volume"; public static final String YEAR = "year"; } diff --git a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java index 35cb282cac8c..a4a006331e90 100644 --- a/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java +++ b/src/main/java/net/sf/jabref/model/entry/InternalBibtexFields.java @@ -68,7 +68,7 @@ public class InternalBibtexFields { "ctlnames_show_etal", "ctlalt_stretch_factor"); public static final List IEEETRANBSTCTL_YES_NO_FIELDS = Arrays.asList("ctluse_article_number", "ctluse_paper", "ctluse_url", "ctluse_forced_etal", "ctluse_alt_spacing", "ctldash_repeated_names"); - public static final List BIBLATEX_DATE_FIELDS = Arrays.asList(FieldName.DATE, "eventdate", "origdate", "urldate"); + public static final List BIBLATEX_DATE_FIELDS = Arrays.asList(FieldName.DATE, "eventdate", "origdate", FieldName.URLDATE); public static final List BIBLATEX_PERSON_NAME_FIELDS = Arrays.asList(FieldName.AUTHOR, FieldName.EDITOR, "editora", "editorb", "editorc", "translator", "annotator", "commentator", "introduction", "foreword", "afterword", "bookauthor", "holder", "shortauthor", "shorteditor", "sortname"); @@ -92,10 +92,10 @@ private InternalBibtexFields(boolean serializeSpecialFields) { // An annotation. It is not used by the standard bibliography styles, // but may be used by others that produce an annotated bibliography. // http://www.ecst.csuchico.edu/~jacobsd/bib/formats/bibtex.html - add(new BibtexSingleField("annote", true, BibtexSingleField.LARGE_W)); + add(new BibtexSingleField(FieldName.ANNOTE, true, BibtexSingleField.LARGE_W)); add(new BibtexSingleField(FieldName.AUTHOR, true, BibtexSingleField.MEDIUM_W, 280)); add(new BibtexSingleField(FieldName.BOOKTITLE, true, 175)); - add(new BibtexSingleField("chapter", true, BibtexSingleField.SMALL_W)); + add(new BibtexSingleField(FieldName.CHAPTER, true, BibtexSingleField.SMALL_W)); dummy = new BibtexSingleField(FieldName.CROSSREF, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.CROSSREF)); add(dummy); @@ -111,7 +111,7 @@ private InternalBibtexFields(boolean serializeSpecialFields) { dummy.setExtras(EnumSet.of(FieldProperties.JOURNAL_NAME)); add(dummy); - add(new BibtexSingleField("key", true)); + add(new BibtexSingleField(FieldName.KEY, true)); dummy = new BibtexSingleField(FieldName.MONTH, true, BibtexSingleField.SMALL_W); dummy.setExtras(EnumSet.of(FieldProperties.MONTH)); add(dummy); @@ -120,7 +120,7 @@ private InternalBibtexFields(boolean serializeSpecialFields) { add(new BibtexSingleField(FieldName.ORGANIZATION, true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField(FieldName.PAGES, true, BibtexSingleField.SMALL_W)); add(new BibtexSingleField(FieldName.PUBLISHER, true, BibtexSingleField.MEDIUM_W)); - add(new BibtexSingleField("school", true, BibtexSingleField.MEDIUM_W)); + add(new BibtexSingleField(FieldName.SCHOOL, true, BibtexSingleField.MEDIUM_W)); add(new BibtexSingleField(FieldName.SERIES, true, BibtexSingleField.SMALL_W)); add(new BibtexSingleField(FieldName.TITLE, true, 400)); dummy = new BibtexSingleField(FieldName.TYPE, true, BibtexSingleField.SMALL_W); @@ -191,7 +191,7 @@ private InternalBibtexFields(boolean serializeSpecialFields) { add(new BibtexSingleField("pmid", false, BibtexSingleField.SMALL_W, 60).setNumeric(true)); // additional fields ------------------------------------------------------ - add(new BibtexSingleField("location", false)); + add(new BibtexSingleField(FieldName.LOCATION, false)); add(new BibtexSingleField(FieldName.ABSTRACT, false, BibtexSingleField.LARGE_W, 400)); dummy = new BibtexSingleField(FieldName.URL, false, BibtexSingleField.SMALL_W); From e333b8f77cbc6a5f3805fbdc76a832e4f381eb44 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sat, 23 Jul 2016 11:58:36 +0200 Subject: [PATCH 265/268] Resolves #1613 Use Jabref default icon for uninstaller for now (#1616) --- jabref.install4j | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jabref.install4j b/jabref.install4j index 6d9c67c460cf..df0f62a24101 100644 --- a/jabref.install4j +++ b/jabref.install4j @@ -59,7 +59,7 @@ - + @@ -97,10 +97,13 @@ - + + + true + false From 0684f55925612c6f80c7636d682a57455f76df0b Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Sat, 23 Jul 2016 12:29:26 +0200 Subject: [PATCH 266/268] Always use https for help files (#1615) --- README.md | 2 +- src/main/java/net/sf/jabref/gui/help/HelpAction.java | 2 +- src/test/java/net/sf/jabref/logic/help/HelpFileTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dedc17e23e0e..f3dbaf5950c6 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Try to double click the `jar` file or execute the following command: ## Documentation -JabRef comes with an [online help](http://help.jabref.org/), accessed by pressing `F1` or clicking on a question mark icon. +JabRef comes with an [online help](https://help.jabref.org/), accessed by pressing `F1` or clicking on a question mark icon. The help is are probably not exhaustive enough to satisfy everyone yet, but it should help sort out the most important issues about using the program. If you choose languages other than English, some or all help pages may appear in your chosen languages. diff --git a/src/main/java/net/sf/jabref/gui/help/HelpAction.java b/src/main/java/net/sf/jabref/gui/help/HelpAction.java index 3be2e2c5059a..68e3f66e4cab 100644 --- a/src/main/java/net/sf/jabref/gui/help/HelpAction.java +++ b/src/main/java/net/sf/jabref/gui/help/HelpAction.java @@ -82,7 +82,7 @@ public void setHelpFile(HelpFile urlPart) { @Override public void actionPerformed(ActionEvent e) { - String url = "http://help.jabref.org/" + Globals.prefs.get(JabRefPreferences.LANGUAGE) + "/" + helpPage.getPageName(); + String url = "https://help.jabref.org/" + Globals.prefs.get(JabRefPreferences.LANGUAGE) + "/" + helpPage.getPageName(); JabRefDesktop.openBrowserShowPopup(url); } } diff --git a/src/test/java/net/sf/jabref/logic/help/HelpFileTest.java b/src/test/java/net/sf/jabref/logic/help/HelpFileTest.java index 1f132d1c5ec7..73c4a9498f92 100644 --- a/src/test/java/net/sf/jabref/logic/help/HelpFileTest.java +++ b/src/test/java/net/sf/jabref/logic/help/HelpFileTest.java @@ -26,7 +26,7 @@ import static junit.framework.TestCase.assertEquals; public class HelpFileTest { - private final String jabrefHelp = "http://help.jabref.org/en/"; + private final String jabrefHelp = "https://help.jabref.org/en/"; @Test public void referToValidPage() throws IOException { for (HelpFile help : HelpFile.values()) { From 458490b10848ee4b4c4d06d74c3140c74452c8d7 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 23 Jul 2016 13:49:53 +0200 Subject: [PATCH 267/268] Implemented #1345 - cleanup ISSN (#1590) * Implemented #1345 - cleanup ISSN * Fixed comments * Extracted ISSN class * Added tests for ISSN and ISBN --- CHANGELOG.md | 1 + .../gui/cleanup/CleanupPresetPanel.java | 11 ++- .../jabref/logic/cleanup/CleanupPreset.java | 12 ++- .../jabref/logic/cleanup/CleanupWorker.java | 3 + .../sf/jabref/logic/cleanup/ISSNCleanup.java | 32 ++++++++ .../jabref/logic/integrity/ISSNChecker.java | 25 ++---- .../java/net/sf/jabref/logic/util/ISBN.java | 4 +- .../java/net/sf/jabref/logic/util/ISSN.java | 52 +++++++++++++ .../jabref/preferences/JabRefPreferences.java | 2 + src/main/resources/l10n/JabRef_da.properties | 2 + src/main/resources/l10n/JabRef_de.properties | 5 ++ src/main/resources/l10n/JabRef_en.properties | 1 + src/main/resources/l10n/JabRef_es.properties | 2 + src/main/resources/l10n/JabRef_fa.properties | 2 + src/main/resources/l10n/JabRef_fr.properties | 2 + src/main/resources/l10n/JabRef_in.properties | 2 + src/main/resources/l10n/JabRef_it.properties | 2 + src/main/resources/l10n/JabRef_ja.properties | 2 + src/main/resources/l10n/JabRef_nl.properties | 2 + src/main/resources/l10n/JabRef_no.properties | 2 + .../resources/l10n/JabRef_pt_BR.properties | 2 + src/main/resources/l10n/JabRef_ru.properties | 2 + src/main/resources/l10n/JabRef_sv.properties | 2 + src/main/resources/l10n/JabRef_tr.properties | 2 + src/main/resources/l10n/JabRef_vi.properties | 2 + src/main/resources/l10n/JabRef_zh.properties | 2 + .../jabref/logic/cleanup/ISSNCleanupTest.java | 57 ++++++++++++++ .../net/sf/jabref/logic/util/ISBNTest.java | 77 +++++++++++++++++++ .../net/sf/jabref/logic/util/ISSNTest.java | 64 +++++++++++++++ 29 files changed, 352 insertions(+), 24 deletions(-) create mode 100644 src/main/java/net/sf/jabref/logic/cleanup/ISSNCleanup.java create mode 100644 src/main/java/net/sf/jabref/logic/util/ISSN.java create mode 100644 src/test/java/net/sf/jabref/logic/cleanup/ISSNCleanupTest.java create mode 100644 src/test/java/net/sf/jabref/logic/util/ISBNTest.java create mode 100644 src/test/java/net/sf/jabref/logic/util/ISSNTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 78f5ca1e4631..74d96acde10f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Added filter to not show selected integrity checks - Enhance the entry customization dialog to give better visual feedback - The arXiv fetcher now also supports free-text search queries +- [#1345](https://github.com/JabRef/jabref/issues/1345) Cleanup ISSN ### Fixed - Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly diff --git a/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java b/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java index 67f1b962c78d..98fc1cbdbea5 100644 --- a/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java +++ b/src/main/java/net/sf/jabref/gui/cleanup/CleanupPresetPanel.java @@ -22,6 +22,7 @@ public class CleanupPresetPanel { private final BibDatabaseContext databaseContext; private JCheckBox cleanUpDOI; + private JCheckBox cleanUpISSN; private JCheckBox cleanUpMovePDF; private JCheckBox cleanUpMakePathsRelative; private JCheckBox cleanUpRenamePDF; @@ -44,6 +45,7 @@ public CleanupPresetPanel(BibDatabaseContext databaseContext, CleanupPreset clea private void init() { cleanUpDOI = new JCheckBox( Localization.lang("Move DOIs from note and URL field to DOI field and remove http prefix")); + cleanUpISSN = new JCheckBox(Localization.lang("Reformat ISSN")); if (databaseContext.getMetaData().getDefaultFileDirectory().isPresent()) { cleanUpMovePDF = new JCheckBox(Localization.lang("Move linked files to default file directory %0", databaseContext.getMetaData().getDefaultFileDirectory().get())); @@ -71,7 +73,7 @@ private void init() { updateDisplay(cleanupPreset); FormLayout layout = new FormLayout("left:15dlu, pref:grow", - "pref, pref, pref, pref, pref, pref, pref,pref, 190dlu, fill:pref:grow,"); + "pref, pref, pref, pref, pref, pref, pref,pref, pref,190dlu, fill:pref:grow,"); FormBuilder builder = FormBuilder.create().layout(layout); builder.add(cleanUpDOI).xyw(1, 1, 2); @@ -84,7 +86,8 @@ private void init() { builder.add(new JLabel(currentPattern)).xy(2, 6); builder.add(cleanUpRenamePDFonlyRelativePaths).xy(2, 7); builder.add(cleanUpBibLatex).xyw(1, 8, 2); - builder.add(cleanUpFormatters).xyw(1, 9, 2); + builder.add(cleanUpISSN).xyw(1, 9, 2); + builder.add(cleanUpFormatters).xyw(1, 10, 2); panel = builder.build(); } @@ -99,6 +102,7 @@ private void updateDisplay(CleanupPreset preset) { cleanUpRenamePDFonlyRelativePaths.setEnabled(cleanUpRenamePDF.isSelected()); cleanUpUpgradeExternalLinks.setSelected(preset.isCleanUpUpgradeExternalLinks()); cleanUpBibLatex.setSelected(preset.isConvertToBiblatex()); + cleanUpBibLatex.setSelected(preset.isCleanUpISSN()); cleanUpFormatters.setValues(preset.getFormatterCleanups()); } @@ -117,6 +121,9 @@ public CleanupPreset getCleanupPreset() { if (cleanUpDOI.isSelected()) { activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_DOI); } + if (cleanUpISSN.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_ISSN); + } if (cleanUpMakePathsRelative.isSelected()) { activeJobs.add(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE); } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java index 76a40d138b48..6817ff702f6a 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java @@ -52,6 +52,9 @@ public static CleanupPreset loadFromPreferences(JabRefPreferences preferences) { if (preferences.getBoolean(JabRefPreferences.CLEANUP_DOI)) { activeJobs.add(CleanupStep.CLEAN_UP_DOI); } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_ISSN)) { + activeJobs.add(CleanupStep.CLEAN_UP_ISSN); + } if (preferences.getBoolean(JabRefPreferences.CLEANUP_MOVE_PDF)) { activeJobs.add(CleanupStep.MOVE_PDF); } @@ -88,6 +91,10 @@ public boolean isCleanUpDOI() { return isActive(CleanupStep.CLEAN_UP_DOI); } + public boolean isCleanUpISSN() { + return isActive(CleanupStep.CLEAN_UP_ISSN); + } + public boolean isFixFileLinks() { return isActive(CleanupStep.FIX_FILE_LINKS); } @@ -114,6 +121,7 @@ public boolean isRenamePdfOnlyRelativePaths() { public void storeInPreferences(JabRefPreferences preferences) { preferences.putBoolean(JabRefPreferences.CLEANUP_DOI, isActive(CleanupStep.CLEAN_UP_DOI)); + preferences.putBoolean(JabRefPreferences.CLEANUP_ISSN, isActive(CleanupStep.CLEAN_UP_ISSN)); preferences.putBoolean(JabRefPreferences.CLEANUP_MOVE_PDF, isActive(CleanupStep.MOVE_PDF)); preferences.putBoolean(JabRefPreferences.CLEANUP_MAKE_PATHS_RELATIVE, isActive(CleanupStep.MAKE_PATHS_RELATIVE)); preferences.putBoolean(JabRefPreferences.CLEANUP_RENAME_PDF, isActive(CleanupStep.RENAME_PDF)); @@ -152,6 +160,8 @@ public enum CleanupStep { */ CONVERT_TO_BIBLATEX, MOVE_PDF, - FIX_FILE_LINKS + FIX_FILE_LINKS, + CLEAN_UP_ISSN } + } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java index 3c6da685d6f4..f0a07136d8bc 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java @@ -68,6 +68,9 @@ private List determineCleanupActions(CleanupPreset preset) { if (preset.isCleanUpDOI()) { jobs.add(new DoiCleanup()); } + if (preset.isCleanUpISSN()) { + jobs.add(new ISSNCleanup()); + } if (preset.isFixFileLinks()) { jobs.add(new FileLinksCleanup()); } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/ISSNCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/ISSNCleanup.java new file mode 100644 index 000000000000..11edf0874c86 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/ISSNCleanup.java @@ -0,0 +1,32 @@ +package net.sf.jabref.logic.cleanup; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import net.sf.jabref.logic.util.ISSN; +import net.sf.jabref.model.FieldChange; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FieldName; + + +public class ISSNCleanup implements CleanupJob { + + @Override + public List cleanup(BibEntry entry) { + Optional issnString = entry.getFieldOptional(FieldName.ISSN); + if (!issnString.isPresent()) { + return Collections.emptyList(); + } + + ISSN issn = new ISSN(issnString.get()); + if (issn.isCanBeCleaned()) { + String newValue = issn.getCleanedISSN(); + FieldChange change = new FieldChange(entry, FieldName.ISSN, issnString.get(), newValue); + entry.setField(FieldName.ISSN, newValue); + return Collections.singletonList(change); + } + return Collections.emptyList(); + } + +} diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java index d08cc2f49440..41e9d66cfcba 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java @@ -2,18 +2,16 @@ import java.util.Collections; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.logic.util.ISSN; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; public class ISSNChecker implements Checker { - private static final Pattern ISSN_PATTERN = Pattern.compile("^\\d{4}-\\d{3}[\\dxX]$"); @Override public List check(BibEntry entry) { @@ -22,26 +20,15 @@ public List check(BibEntry entry) { } // Check that the ISSN is on the correct form - String issn = entry.getFieldOptional(FieldName.ISSN).get().trim(); - Matcher issnMatcher = ISSN_PATTERN.matcher(issn); - if (!issnMatcher.matches()) { + String issnString = entry.getFieldOptional(FieldName.ISSN).get().trim(); + + ISSN issn = new ISSN(issnString); + if (!issn.isValidFormat()) { return Collections.singletonList( new IntegrityMessage(Localization.lang("incorrect format"), entry, FieldName.ISSN)); } - // Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Serial_Number - int sum = 0; - for (int pos = 0; pos <= 7; pos++) { - char c = issn.charAt(pos); - if (pos != 4) { - sum += (c - '0') * ((8 - pos) + (pos > 4 ? 1 : 0)); - } - } - char control = issn.charAt(8); - if ((control == 'x') || (control == 'X')) { - control = '9' + 1; - } - if (((((sum % 11) + control) - '0') == 11) || ((sum % 11) == 0)) { + if (issn.isValidChecksum()) { return Collections.emptyList(); } else { return Collections diff --git a/src/main/java/net/sf/jabref/logic/util/ISBN.java b/src/main/java/net/sf/jabref/logic/util/ISBN.java index b470bb51309e..606882459612 100644 --- a/src/main/java/net/sf/jabref/logic/util/ISBN.java +++ b/src/main/java/net/sf/jabref/logic/util/ISBN.java @@ -44,7 +44,7 @@ public boolean isIsbn13() { // Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Book_Number#Check_digits private boolean isbn10check() { - if ((isbnString == null) || (isbnString.length() != 10)) { + if (isbnString.length() != 10) { return false; } @@ -62,7 +62,7 @@ private boolean isbn10check() { // Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Book_Number#Check_digits private boolean isbn13check() { - if ((isbnString == null) || (isbnString.length() != 13)) { + if (isbnString.length() != 13) { return false; } diff --git a/src/main/java/net/sf/jabref/logic/util/ISSN.java b/src/main/java/net/sf/jabref/logic/util/ISSN.java new file mode 100644 index 000000000000..062b3ce147b6 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/util/ISSN.java @@ -0,0 +1,52 @@ +package net.sf.jabref.logic.util; + +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ISSN { + + private static final Pattern ISSN_PATTERN = Pattern.compile("^\\d{4}-\\d{3}[\\dxX]$"); + private static final Pattern ISSN_PATTERN_NODASH = Pattern.compile("^(\\d{4})(\\d{3}[\\dxX])$"); + + private final String issnString; + + + public ISSN(String issnString) { + this.issnString = Objects.requireNonNull(issnString).trim(); + } + + public boolean isValidFormat() { + Matcher issnMatcher = ISSN_PATTERN.matcher(issnString); + return (issnMatcher.matches()); + } + + public boolean isCanBeCleaned() { + Matcher issnNoDashMatcher = ISSN_PATTERN_NODASH.matcher(issnString); + return (issnNoDashMatcher.matches()); + } + + public String getCleanedISSN() { + Matcher issnNoDashMatcher = ISSN_PATTERN_NODASH.matcher(issnString); + if (issnNoDashMatcher.find()) { + return issnNoDashMatcher.replaceFirst("$1-$2"); + } + return issnString; + } + + public boolean isValidChecksum() { + // Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Serial_Number + int sum = 0; + for (int pos = 0; pos <= 7; pos++) { + char c = issnString.charAt(pos); + if (pos != 4) { + sum += (c - '0') * ((8 - pos) + (pos > 4 ? 1 : 0)); + } + } + char control = issnString.charAt(8); + if ((control == 'x') || (control == 'X')) { + control = '9' + 1; + } + return (((((sum % 11) + control) - '0') == 11) || ((sum % 11) == 0)); + } +} diff --git a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java index 255af2dd4a6d..6fb8e20fe477 100644 --- a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java @@ -344,6 +344,7 @@ public class JabRefPreferences { public static final String AKS_AUTO_NAMING_PDFS_AGAIN = "AskAutoNamingPDFsAgain"; public static final String CLEANUP_DOI = "CleanUpDOI"; + public static final String CLEANUP_ISSN = "CleanUpISSN"; public static final String CLEANUP_MOVE_PDF = "CleanUpMovePDF"; public static final String CLEANUP_MAKE_PATHS_RELATIVE = "CleanUpMakePathsRelative"; public static final String CLEANUP_RENAME_PDF = "CleanUpRenamePDF"; @@ -1386,6 +1387,7 @@ public void setDefaultEncoding(Charset encoding) { private static void insertCleanupPreset(Map storage, CleanupPreset preset) { storage.put(CLEANUP_DOI, preset.isCleanUpDOI()); + storage.put(CLEANUP_ISSN, preset.isCleanUpISSN()); storage.put(CLEANUP_MOVE_PDF, preset.isMovePDF()); storage.put(CLEANUP_MAKE_PATHS_RELATIVE, preset.isMakePathsRelative()); storage.put(CLEANUP_RENAME_PDF, preset.isRenamePDF()); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 67f68b2c23b1..d70e4edfe93d 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1712,3 +1712,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index dee230addbb7..2ac911b35b38 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2428,3 +2428,8 @@ Execute_command=Befehl_ausführen Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.=Hinweis\:_%0_als_Platzhalter_für_den_Speicherort_der_Datenbank_benutzen. Executing_command_\"%0\"...=Ausführung_des_Kommandos_\"%0\"... Error_occured_while_executing_the_command_\"%0\".=Während_der_Ausführung_des_Befehls_\"%0\"_ist_ein_Fehler_aufgetreten. + + + +Reformat_ISSN= + diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 1d87886261e6..b5138fe4b533 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2279,3 +2279,4 @@ Execute_command=Execute_command Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.=Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file. Executing_command_\"%0\"...=Executing_command_\"%0\"... Error_occured_while_executing_the_command_\"%0\".=Error_occured_while_executing_the_command_\"%0\". +Reformat_ISSN=Reformat_ISSN diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index d3ba5a7bec08..92ae1e93eb9c 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1614,3 +1614,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 2d051c0c7221..ad4dab3ea1ed 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2400,3 +2400,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 649d1d731ef7..6ba80289a3e3 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1658,3 +1658,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 3b8b2b2f8183..d2fe693ef80b 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1633,3 +1633,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index b9a6561346df..09e11ff9ab6e 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1733,3 +1733,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index d6cbde88f906..9a04234b8005 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2378,3 +2378,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 95b71fe05df8..29a7ebc15fd7 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2409,3 +2409,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index fb3d3e1f6e00..6bb2693fbfd2 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2805,3 +2805,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index d9d4e1aaf9ba..8e2d9de052e5 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1627,3 +1627,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 578b1a8e65de..edfdc07b6d9e 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2377,3 +2377,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 8e618bc4a72c..6f02c2e93138 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1570,3 +1570,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index daa1a5b68b8e..4d7fb068b00d 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1646,3 +1646,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 8287ab5aaab2..56648ee1c6af 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2401,3 +2401,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index e8949a25a47a..d88f6075e35d 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1640,3 +1640,5 @@ Execute_command= Note\:_Use_the_placeholder_%0_for_the_location_of_the_opened_database_file.= Executing_command_\"%0\"...= Error_occured_while_executing_the_command_\"%0\".= + +Reformat_ISSN= diff --git a/src/test/java/net/sf/jabref/logic/cleanup/ISSNCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/ISSNCleanupTest.java new file mode 100644 index 000000000000..4e69c9c719c0 --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/cleanup/ISSNCleanupTest.java @@ -0,0 +1,57 @@ +package net.sf.jabref.logic.cleanup; + +import java.util.Optional; + +import net.sf.jabref.BibDatabaseContext; +import net.sf.jabref.logic.journals.JournalAbbreviationLoader; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.preferences.JabRefPreferences; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.mockito.Mockito.mock; + +public class ISSNCleanupTest { + + private CleanupWorker worker; + + + @Before + public void setUp() { + worker = new CleanupWorker(mock(BibDatabaseContext.class), mock(JournalAbbreviationLoader.class), + JabRefPreferences.getInstance()); + } + + @Test + public void cleanupISSNReturnsCorrectISSN() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_ISSN); + BibEntry entry = new BibEntry(); + entry.setField("issn", "0123-4567"); + + worker.cleanup(preset, entry); + Assert.assertEquals(Optional.of("0123-4567"), entry.getFieldOptional("issn")); + } + + @Test + public void cleanupISSNAddsMissingDash() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_ISSN); + BibEntry entry = new BibEntry(); + entry.setField("issn", "01234567"); + + worker.cleanup(preset, entry); + Assert.assertEquals(Optional.of("0123-4567"), entry.getFieldOptional("issn")); + } + + @Test + public void cleanupISSNJunkStaysJunk() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_ISSN); + BibEntry entry = new BibEntry(); + entry.setField("issn", "Banana"); + + worker.cleanup(preset, entry); + Assert.assertEquals(Optional.of("Banana"), entry.getFieldOptional("issn")); + } + +} diff --git a/src/test/java/net/sf/jabref/logic/util/ISBNTest.java b/src/test/java/net/sf/jabref/logic/util/ISBNTest.java new file mode 100644 index 000000000000..4d317240e672 --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/util/ISBNTest.java @@ -0,0 +1,77 @@ +package net.sf.jabref.logic.util; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + +public class ISBNTest { + + + @Test + public void testIsValidFormat10Correct() { + assertTrue(new ISBN("0-123456-47-9").isValidFormat()); + assertTrue(new ISBN("0-9752298-0-X").isValidFormat()); + + } + + @Test + public void testIsValidFormat10Incorrect() { + assertFalse(new ISBN("0-12B456-47-9").isValidFormat()); + } + + @Test + public void testIsValidChecksum10Correct() { + assertTrue(new ISBN("0-123456-47-9").isValidChecksum()); + assertTrue(new ISBN("0-9752298-0-X").isValidChecksum()); + assertTrue(new ISBN("0-9752298-0-x").isValidChecksum()); + } + + @Test + public void testIsValidChecksum10Incorrect() { + assertFalse(new ISBN("0-123456-47-8").isValidChecksum()); + } + + @Test + public void testIsValidFormat13Correct() { + assertTrue(new ISBN("978-1-56619-909-4").isValidFormat()); + } + + @Test + public void testIsValidFormat13Incorrect() { + assertFalse(new ISBN("978-1-56619-9O9-4 ").isValidFormat()); + } + + @Test + public void testIsValidChecksum13Correct() { + assertTrue(new ISBN("978-1-56619-909-4 ").isValidChecksum()); + } + + @Test + public void testIsValidChecksum13Incorrect() { + assertFalse(new ISBN("978-1-56619-909-5").isValidChecksum()); + } + + @Test + public void testIsIsbn10Correct() { + assertTrue(new ISBN("0-123456-47-9").isIsbn10()); + assertTrue(new ISBN("0-9752298-0-X").isIsbn10()); + } + + @Test + public void testIsIsbn10Incorrect() { + assertFalse(new ISBN("978-1-56619-909-4").isIsbn10()); + } + + @Test + public void testIsIsbn13Correct() { + assertTrue(new ISBN("978-1-56619-909-4").isIsbn13()); + } + + @Test + public void testIsIsbn13Incorrect() { + assertFalse(new ISBN("0-123456-47-9").isIsbn13()); + } + +} diff --git a/src/test/java/net/sf/jabref/logic/util/ISSNTest.java b/src/test/java/net/sf/jabref/logic/util/ISSNTest.java new file mode 100644 index 000000000000..e8a9fb6b69ab --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/util/ISSNTest.java @@ -0,0 +1,64 @@ +package net.sf.jabref.logic.util; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + +public class ISSNTest { + + + @Test + public void testIsCanBeCleaned() { + assertTrue(new ISSN("00279633").isCanBeCleaned()); + } + + @Test + public void testIsCanBeCleanedIncorrectRubbish() { + assertFalse(new ISSN("A brown fox").isCanBeCleaned()); + } + + @Test + public void testIsCanBeCleanedDashAlreadyThere() { + assertFalse(new ISSN("0027-9633").isCanBeCleaned()); + } + + @Test + public void testGetCleanedISSN() { + assertEquals("0027-9633", new ISSN("00279633").getCleanedISSN()); + } + + @Test + public void testGetCleanedISSNDashAlreadyThere() { + assertEquals("0027-9633", new ISSN("0027-9633").getCleanedISSN()); + } + + @Test + public void testGetCleanedISSNDashRubbish() { + assertEquals("A brown fox", new ISSN("A brown fox").getCleanedISSN()); + } + + @Test + public void testIsValidChecksumCorrect() { + assertTrue(new ISSN("0027-9633").isValidChecksum()); + assertTrue(new ISSN("2434-561X").isValidChecksum()); + assertTrue(new ISSN("2434-561x").isValidChecksum()); + } + + @Test + public void testIsValidChecksumIncorrect() { + assertFalse(new ISSN("0027-9634").isValidChecksum()); + } + + @Test + public void testIsValidFormatCorrect() { + assertTrue(new ISSN("0027-963X").isValidFormat()); + } + + @Test + public void testIsValidFormatIncorrect() { + assertFalse(new ISSN("00279634").isValidFormat()); + } +} From 01a217946a9fb1ebbf7f5f5f1490b571162371e1 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Sat, 23 Jul 2016 17:04:11 +0200 Subject: [PATCH 268/268] Added DateFormatter to LayoutEntry so that it actually works... (#1619) --- src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java index 1172fa871677..09572f3215bf 100644 --- a/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/net/sf/jabref/logic/layout/LayoutEntry.java @@ -54,6 +54,7 @@ import net.sf.jabref.logic.layout.format.CurrentDate; import net.sf.jabref.logic.layout.format.DOICheck; import net.sf.jabref.logic.layout.format.DOIStrip; +import net.sf.jabref.logic.layout.format.DateFormatter; import net.sf.jabref.logic.layout.format.Default; import net.sf.jabref.logic.layout.format.FileLink; import net.sf.jabref.logic.layout.format.FirstPage; @@ -485,6 +486,8 @@ private LayoutFormatter getLayoutFormatterByName(String name) throws Exception { return new CreateDocBookAuthors(); case "CurrentDate": return new CurrentDate(); + case "DateFormatter": + return new DateFormatter(); case "DOICheck": return new DOICheck(); case "DOIStrip":