diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f27c06510..999f428d1cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,12 +25,21 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Replaces manual thread management with cached thread pool - Files can now be moved to subfolders named by a custom format pattern, e.g., based on `entrytype`. The pattern can be specified in the settings like the filename pattern. [#1092](https://github.com/JabRef/jabref/issues/1092) +- Custom EntryTypes are now stored independently for BibTeX and BibLatex mode. + - Upon the first start of JabRef 3.8 old entry type customizations will be converted to custom types for the set default database mode (BibTeX if not changed to BibLatex) +- Upon opening a file with customized entry types it is now possible to choose which customizations should be stored in local preferences. ### Fixed - We fixed a few groups related issues: - "Remove entries from group" no longer removes entries from groups with similar names. [#2334](https://github.com/JabRef/jabref/issues/2334) - If an entry's group field contains 'a b' it is no longer considered a member the groups 'a', 'b', and 'a b'. [1873](https://github.com/JabRef/jabref/issues/1873) - Reading and writing now works for groups that contain special escaped characters in their names. [1681](https://github.com/JabRef/jabref/issues/1681) +- We fixed various problems with customized entry types: + - Resetting the preferences now also resets custom entry types. [#2261](https://github.com/JabRef/jabref/issues/2261) + - Importing preferences does no longer duplicate custom entry types. [#772](https://github.com/JabRef/jabref/issues/772) + - Potenial problems upon resetting to defaults should be fixed. [#772](https://github.com/JabRef/jabref/issues/772) + - Customized standard types (such as `@article`) are no longer listed as "custom" type in "New Entry" dialog. + - Applying changes in the "Custom Entry Types" dialog is now faster. [#2318](https://github.com/JabRef/jabref/issues/2318) - We fixed an issue which prevented JabRef from closing using the "Quit" menu command. [#2336](https://github.com/JabRef/jabref/issues/2336) - We fixed an issue where the file permissions of the .bib-file were changed upon saving [#2279](https://github.com/JabRef/jabref/issues/2279). - We fixed an issue which prevented that a database was saved successfully if JabRef failed to generate new BibTeX-keys [#2285](https://github.com/JabRef/jabref/issues/2285). diff --git a/src/main/java/net/sf/jabref/JabRefMain.java b/src/main/java/net/sf/jabref/JabRefMain.java index 468a0d915b6..df15ff28357 100644 --- a/src/main/java/net/sf/jabref/JabRefMain.java +++ b/src/main/java/net/sf/jabref/JabRefMain.java @@ -7,7 +7,6 @@ import net.sf.jabref.cli.ArgumentProcessor; import net.sf.jabref.gui.remote.JabRefMessageHandler; -import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.exporter.ExportFormat; import net.sf.jabref.logic.exporter.ExportFormats; import net.sf.jabref.logic.exporter.SavePreferences; @@ -23,6 +22,8 @@ import net.sf.jabref.logic.remote.client.RemoteListenerClient; import net.sf.jabref.logic.util.OS; import net.sf.jabref.migrations.PreferencesMigrations; +import net.sf.jabref.model.EntryTypes; +import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.preferences.JabRefPreferences; @@ -60,6 +61,7 @@ private static void start(String[] args) { PreferencesMigrations.upgradeSortOrder(); PreferencesMigrations.upgradeFaultyEncodingStrings(); PreferencesMigrations.upgradeLabelPatternToBibtexKeyPattern(); + PreferencesMigrations.upgradeStoredCustomEntryTypes(); // Update handling of special fields based on preferences InternalBibtexFields @@ -75,7 +77,8 @@ private static void start(String[] args) { /* Build list of Import and Export formats */ Globals.IMPORT_FORMAT_READER.resetImportFormats(Globals.prefs.getImportFormatPreferences(), Globals.prefs.getXMPPreferences()); - CustomEntryTypesManager.loadCustomEntryTypes(preferences); + EntryTypes.loadCustomEntryTypes(preferences.loadCustomEntryTypes(BibDatabaseMode.BIBTEX), + preferences.loadCustomEntryTypes(BibDatabaseMode.BIBLATEX)); Map customFormats = Globals.prefs.customExports.getCustomExportFormats(Globals.prefs, Globals.journalAbbreviationLoader); LayoutFormatterPreferences layoutPreferences = Globals.prefs diff --git a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java index 4b3588a5356..d5512f3abcb 100644 --- a/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/net/sf/jabref/cli/ArgumentProcessor.java @@ -18,7 +18,6 @@ import net.sf.jabref.gui.externalfiles.AutoSetLinks; import net.sf.jabref.gui.importer.fetcher.EntryFetcher; import net.sf.jabref.gui.importer.fetcher.EntryFetchers; -import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.bibtexkeypattern.BibtexKeyPatternUtil; import net.sf.jabref.logic.exporter.BibDatabaseWriter; import net.sf.jabref.logic.exporter.BibtexDatabaseWriter; @@ -42,13 +41,13 @@ import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.OS; import net.sf.jabref.model.Defaults; +import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseContext; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.metadata.MetaData; import net.sf.jabref.model.strings.StringUtil; -import net.sf.jabref.preferences.JabRefPreferences; import net.sf.jabref.preferences.SearchPreferences; import net.sf.jabref.shared.prefs.SharedDatabasePreferences; @@ -299,8 +298,7 @@ private boolean generateAux(List loaded, String[] data) { System.out.println(Localization.lang("Saving") + ": " + subName); SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs); BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter<>(FileSaveSession::new); - Defaults defaults = new Defaults(BibDatabaseMode - .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); + Defaults defaults = new Defaults(Globals.prefs.getDefaultBibDatabaseMode()); SaveSession session = databaseWriter.saveDatabase(new BibDatabaseContext(newBase, defaults), prefs); // Show just a warning message if encoding did not work for all characters: @@ -338,8 +336,7 @@ private void exportFile(List loaded, String[] data) { try { System.out.println(Localization.lang("Saving") + ": " + data[0]); SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs); - Defaults defaults = new Defaults(BibDatabaseMode - .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); + Defaults defaults = new Defaults(Globals.prefs.getDefaultBibDatabaseMode()); BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter<>( FileSaveSession::new); SaveSession session = databaseWriter.saveDatabase( @@ -401,7 +398,8 @@ private void exportFile(List loaded, String[] data) { private void importPreferences() { try { Globals.prefs.importPreferences(cli.getPreferencesImport()); - CustomEntryTypesManager.loadCustomEntryTypes(Globals.prefs); + EntryTypes.loadCustomEntryTypes(Globals.prefs.loadCustomEntryTypes(BibDatabaseMode.BIBTEX), + Globals.prefs.loadCustomEntryTypes(BibDatabaseMode.BIBLATEX)); Map customFormats = Globals.prefs.customExports.getCustomExportFormats(Globals.prefs, Globals.journalAbbreviationLoader); LayoutFormatterPreferences layoutPreferences = Globals.prefs diff --git a/src/main/java/net/sf/jabref/collab/ChangeScanner.java b/src/main/java/net/sf/jabref/collab/ChangeScanner.java index e2aeb320134..8f04cacd95b 100644 --- a/src/main/java/net/sf/jabref/collab/ChangeScanner.java +++ b/src/main/java/net/sf/jabref/collab/ChangeScanner.java @@ -32,14 +32,12 @@ import net.sf.jabref.model.DuplicateCheck; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseContext; -import net.sf.jabref.model.database.BibDatabaseMode; 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.model.groups.GroupTreeNode; import net.sf.jabref.model.metadata.MetaData; -import net.sf.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -152,8 +150,7 @@ private void storeTempDatabase() { .withEncoding(panel.getBibDatabaseContext().getMetaData().getEncoding() .orElse(Globals.prefs.getDefaultEncoding())); - Defaults defaults = new Defaults(BibDatabaseMode - .fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); + Defaults defaults = new Defaults(Globals.prefs.getDefaultBibDatabaseMode()); BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter<>(FileSaveSession::new); SaveSession ss = databaseWriter.saveDatabase(new BibDatabaseContext(databaseInTemp, metadataInTemp, defaults), prefs); ss.commit(Globals.getFileUpdateMonitor().getTempFile(panel.fileMonitorHandle())); diff --git a/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java b/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java index 2fb61ef08cb..57a5ff0ad9e 100644 --- a/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java +++ b/src/main/java/net/sf/jabref/gui/EntryTypeDialog.java @@ -9,6 +9,7 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Collection; +import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; @@ -28,13 +29,13 @@ import net.sf.jabref.Globals; import net.sf.jabref.gui.importer.fetcher.EntryFetchers; import net.sf.jabref.gui.keyboard.KeyBinding; -import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.importer.FetcherException; import net.sf.jabref.logic.importer.IdBasedFetcher; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.EntryTypes; -import net.sf.jabref.model.database.BibDatabaseContext; +import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.BibLatexEntryTypes; import net.sf.jabref.model.entry.BibtexEntryTypes; import net.sf.jabref.model.entry.EntryType; import net.sf.jabref.model.entry.IEEETranEntryTypes; @@ -59,10 +60,8 @@ public class EntryTypeDialog extends JDialog implements ActionListener { private JComboBox comboBox; private final JabRefFrame frame; private static final int COLUMN = 3; - private final boolean biblatexMode; private final CancelAction cancelAction = new CancelAction(); - private final BibDatabaseContext bibDatabaseContext; static class TypeButton extends JButton implements Comparable { @@ -90,10 +89,6 @@ public EntryTypeDialog(JabRefFrame frame) { this.frame = frame; - bibDatabaseContext = frame.getCurrentBasePanel().getBibDatabaseContext(); - biblatexMode = bibDatabaseContext.isBiblatexMode(); - - setTitle(Localization.lang("Select entry type")); addWindowListener(new WindowAdapter() { @@ -115,14 +110,21 @@ private JPanel createEntryGroupsPanel() { JPanel panel = new JPanel(); panel.setLayout(new VerticalLayout()); - if (biblatexMode) { - panel.add(createEntryGroupPanel("BibLateX", EntryTypes.getAllValues(bibDatabaseContext.getMode()))); + if (frame.getCurrentBasePanel().getBibDatabaseContext().isBiblatexMode()) { + panel.add(createEntryGroupPanel("BibLateX", BibLatexEntryTypes.ALL)); + + List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBLATEX); + if (!customTypes.isEmpty()) { + panel.add(createEntryGroupPanel(Localization.lang("Custom"), customTypes)); + } + } else { panel.add(createEntryGroupPanel("BibTeX", BibtexEntryTypes.ALL)); panel.add(createEntryGroupPanel("IEEETran", IEEETranEntryTypes.ALL)); - if (!CustomEntryTypesManager.ALL.isEmpty()) { - panel.add(createEntryGroupPanel(Localization.lang("Custom"), CustomEntryTypesManager.ALL)); + List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBTEX); + if (!customTypes.isEmpty()) { + panel.add(createEntryGroupPanel(Localization.lang("Custom"), customTypes)); } } panel.add(createIdFetcherPanel()); @@ -146,7 +148,7 @@ private JPanel createCancelButtonBarPanel() { return buttons; } - private JPanel createEntryGroupPanel(String groupTitle, Collection entries) { + private JPanel createEntryGroupPanel(String groupTitle, Collection entries) { JPanel panel = new JPanel(); GridBagLayout bagLayout = new GridBagLayout(); panel.setLayout(bagLayout); diff --git a/src/main/java/net/sf/jabref/gui/JabRefFrame.java b/src/main/java/net/sf/jabref/gui/JabRefFrame.java index f0d69659e39..42bd0b7a48c 100644 --- a/src/main/java/net/sf/jabref/gui/JabRefFrame.java +++ b/src/main/java/net/sf/jabref/gui/JabRefFrame.java @@ -76,6 +76,7 @@ import net.sf.jabref.gui.actions.SortTabsAction; import net.sf.jabref.gui.autosaveandbackup.AutosaveUIManager; import net.sf.jabref.gui.bibtexkeypattern.BibtexKeyPatternDialog; +import net.sf.jabref.gui.customentrytypes.EntryCustomizationDialog; import net.sf.jabref.gui.dbproperties.DatabasePropertiesDialog; import net.sf.jabref.gui.exporter.ExportAction; import net.sf.jabref.gui.exporter.ExportCustomizationDialog; @@ -109,7 +110,6 @@ import net.sf.jabref.gui.specialfields.SpecialFieldValueViewModel; import net.sf.jabref.gui.util.WindowLocation; import net.sf.jabref.gui.worker.MarkEntriesAction; -import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.autosaveandbackup.AutosaveManager; import net.sf.jabref.logic.autosaveandbackup.BackupManager; import net.sf.jabref.logic.help.HelpFile; @@ -788,7 +788,6 @@ private void tearDownJabRef(List filenames) { fileHistory.storeHistory(); prefs.customExports.store(Globals.prefs); prefs.customImports.store(); - CustomEntryTypesManager.saveCustomEntryTypes(prefs); prefs.flush(); 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 20eca4b8e46..1b0932eb7a7 100644 --- a/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/NewSubDatabaseAction.java @@ -12,8 +12,6 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.Defaults; import net.sf.jabref.model.database.BibDatabaseContext; -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. @@ -39,8 +37,7 @@ public void actionPerformed(ActionEvent e) { dialog.setVisible(true); if (dialog.generatePressed()) { - Defaults defaults = new Defaults( - BibDatabaseMode.fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); + Defaults defaults = new Defaults(Globals.prefs.getDefaultBibDatabaseMode()); 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/customentrytypes/CustomEntryTypesManager.java b/src/main/java/net/sf/jabref/gui/customentrytypes/CustomEntryTypesManager.java new file mode 100644 index 00000000000..7d7df930bd6 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/customentrytypes/CustomEntryTypesManager.java @@ -0,0 +1,32 @@ +package net.sf.jabref.gui.customentrytypes; + +import java.util.List; +import java.util.stream.Collectors; + +import net.sf.jabref.model.EntryTypes; +import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.model.entry.CustomEntryType; +import net.sf.jabref.preferences.JabRefPreferences; + +public class CustomEntryTypesManager { + + /** + * Iterate through all entry types, and store those that are + * custom defined to preferences. This method is called from + * JabRefFrame when the program closes. + */ + public static void saveCustomEntryTypes(JabRefPreferences prefs) { + saveCustomEntryTypes(prefs, BibDatabaseMode.BIBTEX); + saveCustomEntryTypes(prefs, BibDatabaseMode.BIBLATEX); + + } + + private static void saveCustomEntryTypes(JabRefPreferences prefs, BibDatabaseMode mode) { + List customBiblatexTypes = EntryTypes.getAllValues(mode).stream() + .filter(type -> type instanceof CustomEntryType) + .map(entryType -> (CustomEntryType) entryType).collect(Collectors.toList()); + + prefs.storeCustomEntryTypes(customBiblatexTypes, mode); + } + +} diff --git a/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java b/src/main/java/net/sf/jabref/gui/customentrytypes/EntryCustomizationDialog.java similarity index 78% rename from src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java rename to src/main/java/net/sf/jabref/gui/customentrytypes/EntryCustomizationDialog.java index 04a4bbe9ecc..5021aded964 100644 --- a/src/main/java/net/sf/jabref/gui/EntryCustomizationDialog.java +++ b/src/main/java/net/sf/jabref/gui/customentrytypes/EntryCustomizationDialog.java @@ -1,4 +1,4 @@ -package net.sf.jabref.gui; +package net.sf.jabref.gui.customentrytypes; import java.awt.BorderLayout; import java.awt.Container; @@ -8,12 +8,15 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import javax.swing.AbstractAction; import javax.swing.ActionMap; @@ -33,6 +36,8 @@ import javax.swing.table.AbstractTableModel; import net.sf.jabref.Globals; +import net.sf.jabref.gui.BasePanel; +import net.sf.jabref.gui.JabRefFrame; import net.sf.jabref.gui.keyboard.KeyBinding; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.EntryTypes; @@ -59,8 +64,6 @@ public class EntryCustomizationDialog extends JDialog implements ListSelectionLi private JButton apply; protected JButton helpButton; protected JButton delete; - protected JButton importTypes; - protected JButton exportTypes; private final List preset = InternalBibtexFields.getAllPublicFieldNames(); private String lastSelected; private final Map> reqLists = new HashMap<>(); @@ -188,13 +191,13 @@ public void valueChanged(ListSelectionEvent e) { } } - String s = typeComp.getFirstSelected(); - if (s == null) { + String selectedTypeName = typeComp.getFirstSelected(); + if (selectedTypeName == null) { return; } - List rl = reqLists.get(s); - if (rl == null) { - Optional type = EntryTypes.getType(s, bibDatabaseMode); + List requiredFieldsSelectedType = reqLists.get(selectedTypeName); + if (requiredFieldsSelectedType == null) { + Optional type = EntryTypes.getType(selectedTypeName, bibDatabaseMode); if (type.isPresent()) { List req = type.get().getRequiredFields(); @@ -226,33 +229,35 @@ public void valueChanged(ListSelectionEvent e) { reqComp.requestFocus(); } } else { - reqComp.setFields(rl); - optComp.setFields(optLists.get(s)); + reqComp.setFields(requiredFieldsSelectedType); + optComp.setFields(optLists.get(selectedTypeName)); if (biblatexMode) { - optComp2.setFields(opt2Lists.get(s)); + optComp2.setFields(opt2Lists.get(selectedTypeName)); } } - lastSelected = s; - typeComp.enable(s, changed.contains(lastSelected) && !defaulted.contains(lastSelected)); + lastSelected = selectedTypeName; + typeComp.enable(selectedTypeName, changed.contains(lastSelected) && !defaulted.contains(lastSelected)); } private void applyChanges() { valueChanged(new ListSelectionEvent(new JList<>(), 0, 0, false)); - // Iterate over our map of required fields, and list those types if necessary: + List actuallyChangedTypes = new ArrayList<>(); + + // Iterate over our map of required fields, and list those types if necessary: List types = typeComp.getFields(); for (Map.Entry> stringListEntry : reqLists.entrySet()) { if (!types.contains(stringListEntry.getKey())) { continue; } - List reqStr = stringListEntry.getValue(); - List optStr = optLists.get(stringListEntry.getKey()); - List opt2Str = opt2Lists.get(stringListEntry.getKey()); + List requiredFieldsList = stringListEntry.getValue(); + List optionalFieldsList = optLists.get(stringListEntry.getKey()); + List secondaryOptionalFieldsLists = opt2Lists.get(stringListEntry.getKey()); - if (opt2Str == null) { - opt2Str = new ArrayList<>(0); + if (secondaryOptionalFieldsLists == null) { + secondaryOptionalFieldsLists = new ArrayList<>(0); } // If this type is already existing, check if any changes have @@ -261,57 +266,63 @@ private void applyChanges() { if (defaulted.contains(stringListEntry.getKey())) { // This type should be reverted to its default setup. - String nm = StringUtil.capitalizeFirst(stringListEntry.getKey()); - EntryTypes.removeType(nm, bibDatabaseMode); + EntryTypes.removeType(stringListEntry.getKey(), bibDatabaseMode); - updateTypesForEntries(); + actuallyChangedTypes.add(stringListEntry.getKey().toLowerCase(Locale.ENGLISH)); + defaulted.remove(stringListEntry.getKey()); continue; } Optional oldType = EntryTypes.getType(stringListEntry.getKey(), bibDatabaseMode); if (oldType.isPresent()) { - List oldReq = oldType.get().getRequiredFieldsFlat(); - List oldOpt = oldType.get().getOptionalFields(); + List oldRequiredFieldsList = oldType.get().getRequiredFieldsFlat(); + List oldOptionalFieldsList = oldType.get().getOptionalFields(); if (biblatexMode) { - List oldPriOpt = oldType.get().getPrimaryOptionalFields(); - List oldSecOpt = oldType.get().getSecondaryOptionalFields(); - if (equalLists(oldReq, reqStr) && equalLists(oldPriOpt, optStr) && - equalLists(oldSecOpt, opt2Str)) { + List oldPrimaryOptionalFieldsLists = oldType.get().getPrimaryOptionalFields(); + List oldSecondaryOptionalFieldsList = oldType.get().getSecondaryOptionalFields(); + if (equalLists(oldRequiredFieldsList, requiredFieldsList) && equalLists(oldPrimaryOptionalFieldsLists, optionalFieldsList) && + equalLists(oldSecondaryOptionalFieldsList, secondaryOptionalFieldsLists)) { changesMade = false; } - } else if (equalLists(oldReq, reqStr) && equalLists(oldOpt, optStr)) { + } else if (equalLists(oldRequiredFieldsList, requiredFieldsList) && equalLists(oldOptionalFieldsList, optionalFieldsList)) { changesMade = false; } } if (changesMade) { - CustomEntryType typ = biblatexMode ? - new CustomEntryType(StringUtil.capitalizeFirst(stringListEntry.getKey()), reqStr, optStr, opt2Str) : - new CustomEntryType(StringUtil.capitalizeFirst(stringListEntry.getKey()), reqStr, optStr); + CustomEntryType customType = biblatexMode ? + new CustomEntryType(StringUtil.capitalizeFirst(stringListEntry.getKey()), requiredFieldsList, optionalFieldsList, secondaryOptionalFieldsLists) : + new CustomEntryType(StringUtil.capitalizeFirst(stringListEntry.getKey()), requiredFieldsList, optionalFieldsList); - EntryTypes.addOrModifyCustomEntryType(typ); - updateTypesForEntries(); + EntryTypes.addOrModifyCustomEntryType(customType, bibDatabaseMode); + actuallyChangedTypes.add(customType.getName().toLowerCase(Locale.ENGLISH)); } } - Set toRemove = new HashSet<>(); - for (String o : EntryTypes.getAllTypes(bibDatabaseMode)) { - if (!types.contains(o)) { - toRemove.add(o); + // update all affected entries if something has been changed + if(!actuallyChangedTypes.isEmpty()) { + updateEntriesForChangedTypes(actuallyChangedTypes); + } + + Set typesToRemove = new HashSet<>(); + for (String existingType : EntryTypes.getAllTypes(bibDatabaseMode)) { + if (!types.contains(existingType)) { + typesToRemove.add(existingType); } } // Remove those that should be removed: - if (!toRemove.isEmpty()) { - for (Object aToRemove : toRemove) { - typeDeletion((String) aToRemove); + if (!typesToRemove.isEmpty()) { + for (String typeToRemove : typesToRemove) { + deleteType(typeToRemove); } } updateTables(); + CustomEntryTypesManager.saveCustomEntryTypes(Globals.prefs); } - private void typeDeletion(String name) { + private void deleteType(String name) { Optional type = EntryTypes.getType(name, bibDatabaseMode); if (type.isPresent() && (type.get() instanceof CustomEntryType)) { @@ -328,7 +339,7 @@ private void typeDeletion(String name) { } } EntryTypes.removeType(name, bibDatabaseMode); - updateTypesForEntries(); + updateEntriesForChangedTypes(Arrays.asList(name.toLowerCase(Locale.ENGLISH))); changed.remove(name); reqLists.remove(name); optLists.remove(name); @@ -372,17 +383,14 @@ public void actionPerformed(ActionEvent e) { } } - /** - * Cycle through all databases, and make sure everything is updated with - * the new type customization. This includes making sure all entries have - * a valid type, that no obsolete entry editors are around, and that - * the right-click menus' change type menu is up-to-date. - */ - private void updateTypesForEntries() { + private void updateEntriesForChangedTypes(List actuallyChangedTypes) { for (BasePanel bp : frame.getBasePanelList()) { - for (BibEntry entry : bp.getDatabase().getEntries()) { - EntryTypes.getType(entry.getType(), bibDatabaseMode).ifPresent(entry::setType); - } + // get all affected entries + List filtered = bp.getDatabase().getEntries().stream() + .filter(entry -> actuallyChangedTypes.contains(entry.getType().toLowerCase(Locale.ENGLISH))).collect(Collectors.toList()); + + // update all affected entries with new type + filtered.forEach(entry -> EntryTypes.getType(entry.getType(), bibDatabaseMode).ifPresent(entry::setType)); } } diff --git a/src/main/java/net/sf/jabref/gui/EntryTypeList.java b/src/main/java/net/sf/jabref/gui/customentrytypes/EntryTypeList.java similarity index 99% rename from src/main/java/net/sf/jabref/gui/EntryTypeList.java rename to src/main/java/net/sf/jabref/gui/customentrytypes/EntryTypeList.java index 07bb4168568..263dba7d61a 100644 --- a/src/main/java/net/sf/jabref/gui/EntryTypeList.java +++ b/src/main/java/net/sf/jabref/gui/customentrytypes/EntryTypeList.java @@ -1,4 +1,4 @@ -package net.sf.jabref.gui; +package net.sf.jabref.gui.customentrytypes; import java.awt.GridBagConstraints; import java.awt.event.ActionEvent; diff --git a/src/main/java/net/sf/jabref/gui/FieldSetComponent.java b/src/main/java/net/sf/jabref/gui/customentrytypes/FieldSetComponent.java similarity index 99% rename from src/main/java/net/sf/jabref/gui/FieldSetComponent.java rename to src/main/java/net/sf/jabref/gui/customentrytypes/FieldSetComponent.java index b50bc101fa7..12807b0f45e 100644 --- a/src/main/java/net/sf/jabref/gui/FieldSetComponent.java +++ b/src/main/java/net/sf/jabref/gui/customentrytypes/FieldSetComponent.java @@ -1,4 +1,4 @@ -package net.sf.jabref.gui; +package net.sf.jabref.gui.customentrytypes; import java.awt.Component; import java.awt.GridBagConstraints; @@ -33,6 +33,7 @@ import javax.swing.event.ListSelectionListener; import net.sf.jabref.Globals; +import net.sf.jabref.gui.IconTheme; import net.sf.jabref.logic.bibtexkeypattern.BibtexKeyPatternUtil; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.preferences.JabRefPreferences; diff --git a/src/main/java/net/sf/jabref/gui/importer/ImportInspectionDialog.java b/src/main/java/net/sf/jabref/gui/importer/ImportInspectionDialog.java index 102e9b668b0..bbd9dd27f5b 100644 --- a/src/main/java/net/sf/jabref/gui/importer/ImportInspectionDialog.java +++ b/src/main/java/net/sf/jabref/gui/importer/ImportInspectionDialog.java @@ -88,7 +88,6 @@ import net.sf.jabref.model.FieldChange; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseContext; -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.FieldName; @@ -703,8 +702,7 @@ 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(Globals.prefs.getDefaultBibDatabaseMode()); panel = new BasePanel(frame, new BibDatabaseContext(defaults)); } diff --git a/src/main/java/net/sf/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java b/src/main/java/net/sf/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java index 0eba5d1bdc7..7cb065776f4 100644 --- a/src/main/java/net/sf/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java +++ b/src/main/java/net/sf/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java @@ -1,21 +1,28 @@ package net.sf.jabref.gui.importer.actions; -import java.util.Arrays; -import java.util.Iterator; +import java.awt.Font; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.swing.BoxLayout; +import javax.swing.JCheckBox; +import javax.swing.JLabel; import javax.swing.JOptionPane; +import javax.swing.JPanel; import net.sf.jabref.Globals; import net.sf.jabref.gui.BasePanel; +import net.sf.jabref.gui.customentrytypes.CustomEntryTypesManager; import net.sf.jabref.logic.importer.ParserResult; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.Defaults; import net.sf.jabref.model.EntryTypes; -import net.sf.jabref.model.database.BibDatabaseContext; 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 @@ -24,42 +31,106 @@ public class CheckForNewEntryTypesAction implements PostOpenAction { @Override - public boolean isActionNecessary(ParserResult pr) { - Defaults defaults = new Defaults(BibDatabaseMode.fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); - BibDatabaseMode mode = new BibDatabaseContext(pr.getDatabase(), pr.getMetaData(), defaults).getMode(); - // See if any custom entry types were imported, but disregard those we already know: - for (Iterator i = pr.getEntryTypes().keySet().iterator(); i.hasNext();) { - String typeName = i.next().toLowerCase(); - if (EntryTypes.getType(typeName, mode).isPresent()) { - i.remove(); - } - } - return !pr.getEntryTypes().isEmpty(); + public boolean isActionNecessary(ParserResult parserResult) { + return !getListOfUnknownAndUnequalCustomizations(parserResult).isEmpty(); } @Override - public void performAction(BasePanel panel, ParserResult pr) { - - StringBuilder sb = new StringBuilder(); - sb.append(Localization.lang("Custom entry types found in file")).append(": "); - Object[] types = pr.getEntryTypes().keySet().toArray(); - Arrays.sort(types); - for (Object type : types) { - sb.append(type).append(", "); + public void performAction(BasePanel panel, ParserResult parserResult) { + + BibDatabaseMode mode = getBibDatabaseModeFromParserResult(parserResult); + + List typesToStore = determineEntryTypesToSave(panel, getListOfUnknownAndUnequalCustomizations(parserResult), mode); + + if (!typesToStore.isEmpty()) { + typesToStore.forEach(type -> EntryTypes.addOrModifyCustomEntryType((CustomEntryType) type, mode)); + CustomEntryTypesManager.saveCustomEntryTypes(Globals.prefs); } - String s = sb.toString(); + } + + private List getListOfUnknownAndUnequalCustomizations(ParserResult parserResult) { + BibDatabaseMode mode = getBibDatabaseModeFromParserResult(parserResult); + + return parserResult.getEntryTypes().values().stream() + .filter(type -> + (!EntryTypes.getType(type.getName(), mode).isPresent()) + || !EntryTypes.isEqualNameAndFieldBased(type, EntryTypes.getType(type.getName(), mode).get())) + .collect(Collectors.toList()); + } + + private List determineEntryTypesToSave(BasePanel panel, List allCustomizedEntryTypes, BibDatabaseMode databaseMode) { + List newTypes = new ArrayList<>(); + List differentCustomizations = new ArrayList<>(); + + for (EntryType customType : allCustomizedEntryTypes) { + if (!EntryTypes.getType(customType.getName(), databaseMode).isPresent()) { + newTypes.add(customType); + } else { + EntryType currentlyStoredType = EntryTypes.getType(customType.getName(), databaseMode).get(); + if (!EntryTypes.isEqualNameAndFieldBased(customType, currentlyStoredType)) { + differentCustomizations.add(customType); + } + } + } + + Map typeCheckBoxMap = new HashMap<>(); + + JPanel checkboxPanel = createCheckBoxPanel(newTypes, differentCustomizations, typeCheckBoxMap); + int answer = JOptionPane.showConfirmDialog(panel.frame(), - s.substring(0, s.length() - 2) + ".\n" - + Localization.lang("Remember these entry types?"), + checkboxPanel, Localization.lang("Custom entry types"), - JOptionPane.YES_NO_OPTION, + JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (answer == JOptionPane.YES_OPTION) { - // Import - for (EntryType typ : pr.getEntryTypes().values()) { - EntryTypes.addOrModifyCustomEntryType((CustomEntryType) typ); + return typeCheckBoxMap.entrySet().stream().filter(entry -> entry.getValue().isSelected()) + .map(Map.Entry::getKey).collect(Collectors.toList()); + } else { + return Collections.emptyList(); + } + + } + + private JPanel createCheckBoxPanel(List newTypes, List differentCustomizations, + Map typeCheckBoxMap) { + JPanel checkboxPanel = new JPanel(); + checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.PAGE_AXIS)); + + JLabel customFoundLabel = new JLabel(Localization.lang("Custom entry types found in file")+"."); + Font boldStandardFont = new Font(customFoundLabel.getFont().getFontName(), Font.BOLD, customFoundLabel.getFont().getSize()); + customFoundLabel.setFont(boldStandardFont); + checkboxPanel.add(customFoundLabel); + + JLabel selectLabel = new JLabel(Localization.lang("Select all customized types to be stored in local preferences")+":"); + selectLabel.setFont(boldStandardFont); + checkboxPanel.add(selectLabel); + + checkboxPanel.add(new JLabel(" ")); + + // add all unknown types: + if (!newTypes.isEmpty()) { + checkboxPanel.add(new JLabel(Localization.lang("Currently unknown") + ":")); + for (EntryType type : newTypes) { + JCheckBox box = new JCheckBox(type.getName(), true); + checkboxPanel.add(box); + typeCheckBoxMap.put(type, box); } } + + // add all different customizations + if (!differentCustomizations.isEmpty()) { + checkboxPanel.add(new JLabel(Localization.lang("Different Customization, current settings will be overwritten") + ":")); + for (EntryType type : differentCustomizations) { + JCheckBox box = new JCheckBox(type.getName(), true); + checkboxPanel.add(box); + typeCheckBoxMap.put(type, box); + } + } + return checkboxPanel; + } + + private BibDatabaseMode getBibDatabaseModeFromParserResult(ParserResult parserResult) { + return parserResult.getMetaData().getMode().orElse(Globals.prefs.getDefaultBibDatabaseMode()); } } diff --git a/src/main/java/net/sf/jabref/gui/menus/ChangeEntryTypeMenu.java b/src/main/java/net/sf/jabref/gui/menus/ChangeEntryTypeMenu.java index 73a9106d01c..4609c5d457d 100644 --- a/src/main/java/net/sf/jabref/gui/menus/ChangeEntryTypeMenu.java +++ b/src/main/java/net/sf/jabref/gui/menus/ChangeEntryTypeMenu.java @@ -2,6 +2,7 @@ import java.awt.Font; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.swing.JMenu; @@ -13,7 +14,6 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.actions.ChangeTypeAction; import net.sf.jabref.gui.keyboard.KeyBinding; -import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.EntryTypes; import net.sf.jabref.model.database.BibDatabaseMode; @@ -57,19 +57,31 @@ private void populateChangeEntryTypeMenu(JMenu menu, BasePanel panel) { for (EntryType type : EntryTypes.getAllValues(BibDatabaseMode.BIBLATEX)) { menu.add(new ChangeTypeAction(type, panel)); } + + List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBLATEX); + if (!customTypes.isEmpty()) { + menu.addSeparator(); + // custom types + createEntryTypeSection(panel, menu, "Custom Entries", customTypes); + } } else { // Bibtex createEntryTypeSection(panel, menu, "BibTeX Entries", BibtexEntryTypes.ALL); menu.addSeparator(); // ieeetran createEntryTypeSection(panel, menu, "IEEETran Entries", IEEETranEntryTypes.ALL); - menu.addSeparator(); - // custom types - createEntryTypeSection(panel, menu, "Custom Entries", CustomEntryTypesManager.ALL); + + + List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBTEX); + if (!customTypes.isEmpty()) { + menu.addSeparator(); + // custom types + createEntryTypeSection(panel, menu, "Custom Entries", customTypes); + } } } - private void createEntryTypeSection(BasePanel panel, JMenu menu, String title, java.util.List types) { + private void createEntryTypeSection(BasePanel panel, JMenu menu, String title, List types) { // bibtex JMenuItem header = new JMenuItem(title); Font font = new Font(menu.getFont().getName(), Font.ITALIC, menu.getFont().getSize()); 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 39d97f685f3..b981728d63e 100644 --- a/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/net/sf/jabref/gui/openoffice/OpenOfficePanel.java @@ -55,9 +55,7 @@ import net.sf.jabref.model.Defaults; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseContext; -import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.FormBuilder; @@ -329,8 +327,7 @@ private void exportEntries() { Localization.lang("Unable to generate new database"), JOptionPane.ERROR_MESSAGE); } - Defaults defaults = new Defaults( - BibDatabaseMode.fromPreference(Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); + Defaults defaults = new Defaults(Globals.prefs.getDefaultBibDatabaseMode()); BibDatabaseContext databaseContext = new BibDatabaseContext(newDatabase, defaults); this.frame.addTab(databaseContext, true); diff --git a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java b/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java deleted file mode 100644 index 855698424fe..00000000000 --- a/src/main/java/net/sf/jabref/logic/CustomEntryTypesManager.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.sf.jabref.logic; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; - -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 { - - public static final List ALL = new ArrayList<>(); - /** - * Load all custom entry types from preferences. This method is - * called from JabRef when the program starts. - */ - public static void loadCustomEntryTypes(JabRefPreferences prefs) { - int number = 0; - Optional type; - while ((type = prefs.getCustomEntryType(number)).isPresent()) { - EntryTypes.addOrModifyCustomEntryType(type.get()); - ALL.add(type.get()); - number++; - } - } - - /** - * Iterate through all entry types, and store those that are - * custom defined to preferences. This method is called from - * JabRefFrame when the program closes. - */ - public static void saveCustomEntryTypes(JabRefPreferences prefs) { - Iterator iterator = EntryTypes.getAllValues(BibDatabaseMode.BIBTEX).iterator(); - int number = 0; - - while (iterator.hasNext()) { - EntryType entryType = iterator.next(); - if (entryType instanceof CustomEntryType) { - // Store this entry type. - prefs.storeCustomEntryType((CustomEntryType) entryType, number); - number++; - } - } - // Then, if there are more 'old' custom types defined, remove these - // from preferences. This is necessary if the number of custom types - // has decreased. - prefs.purgeCustomEntryTypes(number); - } - -} diff --git a/src/main/java/net/sf/jabref/migrations/CustomEntryTypePreferenceMigration.java b/src/main/java/net/sf/jabref/migrations/CustomEntryTypePreferenceMigration.java new file mode 100644 index 00000000000..ca547f4f68b --- /dev/null +++ b/src/main/java/net/sf/jabref/migrations/CustomEntryTypePreferenceMigration.java @@ -0,0 +1,62 @@ +package net.sf.jabref.migrations; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import net.sf.jabref.Globals; +import net.sf.jabref.gui.customentrytypes.CustomEntryTypesManager; +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.strings.StringUtil; +import net.sf.jabref.preferences.JabRefPreferences; + +class CustomEntryTypePreferenceMigration { + + //non-default preferences + private static final String CUSTOM_TYPE_NAME = "customTypeName_"; + private static final String CUSTOM_TYPE_REQ = "customTypeReq_"; + private static final String CUSTOM_TYPE_OPT = "customTypeOpt_"; + private static final String CUSTOM_TYPE_PRIOPT = "customTypePriOpt_"; + + private static JabRefPreferences prefs = Globals.prefs; + + static void upgradeStoredCustomEntryTypes(BibDatabaseMode defaultBibDatabaseMode) { + List storedOldTypes = new ArrayList<>(); + + int number = 0; + Optional type; + while ((type = getCustomEntryType(number)).isPresent()) { + EntryTypes.addOrModifyCustomEntryType(type.get(), defaultBibDatabaseMode); + storedOldTypes.add(type.get()); + number++; + } + + CustomEntryTypesManager.saveCustomEntryTypes(prefs); + } + + /** + * Retrieves all deprecated information about the entry type in preferences, with the tag given by number. + * + * (old implementation which has been copied) + */ + private static Optional getCustomEntryType(int number) { + String nr = String.valueOf(number); + String name = prefs.get(CUSTOM_TYPE_NAME + nr); + if (name == null) { + return Optional.empty(); + } + List req = prefs.getStringList(CUSTOM_TYPE_REQ + nr); + List opt = prefs.getStringList(CUSTOM_TYPE_OPT + nr); + List priOpt = prefs.getStringList(CUSTOM_TYPE_PRIOPT + nr); + if (priOpt.isEmpty()) { + return Optional.of(new CustomEntryType(StringUtil.capitalizeFirst(name), req, opt)); + } + List secondary = new ArrayList<>(opt); + secondary.removeAll(priOpt); + + return Optional.of(new CustomEntryType(StringUtil.capitalizeFirst(name), req, priOpt, secondary)); + + } +} diff --git a/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java b/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java index 49d10f2b496..8ea839abe4e 100644 --- a/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/net/sf/jabref/migrations/PreferencesMigrations.java @@ -88,7 +88,28 @@ public static void upgradeSortOrder() { } /** - * Migrate LabelPattern configuration from version 3.3-3.5 to new BibtexKeyPatterns + * Migrate all customized entry types from versions <=3.7 + */ + public static void upgradeStoredCustomEntryTypes() { + + JabRefPreferences prefs = Globals.prefs; + Preferences mainPrefsNode = Preferences.userNodeForPackage(JabRefMain.class); + + try { + if (mainPrefsNode.nodeExists(JabRefPreferences.CUSTOMIZED_BIBTEX_TYPES) || + mainPrefsNode.nodeExists(JabRefPreferences.CUSTOMIZED_BIBLATEX_TYPES) ) { + // skip further processing as prefs already have been migrated + } else { + LOGGER.info("Migrating old custom entry types."); + CustomEntryTypePreferenceMigration.upgradeStoredCustomEntryTypes(prefs.getDefaultBibDatabaseMode()); + } + } catch (BackingStoreException ex) { + LOGGER.error("Migrating old custom entry types failed.", ex); + } + } + + /** + * Migrate LabelPattern configuration from versions <=3.5 to new BibtexKeyPatterns */ public static void upgradeLabelPatternToBibtexKeyPattern() { diff --git a/src/main/java/net/sf/jabref/model/EntryTypes.java b/src/main/java/net/sf/jabref/model/EntryTypes.java index 7f9d5742141..16e42764640 100644 --- a/src/main/java/net/sf/jabref/model/EntryTypes.java +++ b/src/main/java/net/sf/jabref/model/EntryTypes.java @@ -129,13 +129,12 @@ public static Optional getStandardType(String name, BibDatabaseMode m return mode == BibDatabaseMode.BIBLATEX ? BIBLATEX.getStandardType(name) : BIBTEX.getStandardType(name); } - public static void addOrModifyCustomEntryType(CustomEntryType customEntryType) { - addOrModifyEntryType(customEntryType); - } - - private static void addOrModifyEntryType(EntryType name) { - BIBLATEX.addOrModifyEntryType(name); - BIBTEX.addOrModifyEntryType(name); + public static void addOrModifyCustomEntryType(CustomEntryType customEntryType, BibDatabaseMode mode) { + if(BibDatabaseMode.BIBLATEX == mode) { + BIBLATEX.addOrModifyEntryType(customEntryType); + } else if (BibDatabaseMode.BIBTEX == mode) { + BIBTEX.addOrModifyEntryType(customEntryType); + } } public static Set getAllTypes(BibDatabaseMode type) { @@ -146,6 +145,40 @@ public static Collection getAllValues(BibDatabaseMode type) { return type == BibDatabaseMode.BIBLATEX ? BIBLATEX.getAllValues() : BIBTEX.getAllValues(); } + /** + * Determine all CustomTypes which are not overwritten standard types but real custom types for a given BibDatabaseMode + * + * I.e., a modified "article" type will not be included in the list, but an EntryType like "MyCustomType" will be included. + * + * @param mode the BibDatabaseMode to be checked + * @return the list of all found custom types + */ + public static List getAllCustomTypes(BibDatabaseMode mode) { + Collection allTypes = getAllValues(mode); + if(mode == BibDatabaseMode.BIBTEX) { + return allTypes.stream().filter(entryType -> !BibtexEntryTypes.getType(entryType.getName()).isPresent()) + .filter(entryType -> !IEEETranEntryTypes.getType(entryType.getName()).isPresent()) + .collect(Collectors.toList()); + } else { + return allTypes.stream().filter(entryType -> !BibLatexEntryTypes.getType(entryType.getName()).isPresent()) + .collect(Collectors.toList()); + } + } + + public static List getAllModifiedStandardTypes(BibDatabaseMode mode) { + if (mode == BibDatabaseMode.BIBTEX) { + return getAllModifiedStandardTypes(BIBTEX); + } else { + return getAllModifiedStandardTypes(BIBLATEX); + } + } + + private static List getAllModifiedStandardTypes(InternalEntryTypes internalTypes) { + return internalTypes.getAllValues().stream().filter(type -> type instanceof CustomEntryType) + .filter(type -> internalTypes.getStandardType(type.getName()).isPresent()) + .collect(Collectors.toList()); + } + /** * Removes a customized entry type from the type map. If this type * overrode a standard type, we reinstate the standard one. @@ -172,6 +205,39 @@ public static void removeAllCustomEntryTypes() { } } + /** + * Load given custom entry types for BibTeX and BibLatex mode + */ + public static void loadCustomEntryTypes(List customBibtexEntryTypes, List customBibLatexEntryTypes) { + for (CustomEntryType type : customBibtexEntryTypes) { + EntryTypes.addOrModifyCustomEntryType(type, BibDatabaseMode.BIBTEX); + } + + for (CustomEntryType type : customBibLatexEntryTypes) { + EntryTypes.addOrModifyCustomEntryType(type, BibDatabaseMode.BIBLATEX); + } + } + + /** + * Checks whether two EntryTypes are equal or not based on the equality of the type names and on the equality of + * the required and optional field lists + * + * @param type1 the first EntryType to compare + * @param type2 the secend EntryType to compare + * @return returns true if the two compared entry types have the same name and equal required and optional fields + */ + public static boolean isEqualNameAndFieldBased(EntryType type1, EntryType type2) { + if (type1 == null && type2 == null) { + return true; + } else if (type1 == null || type2 == null) { + return false; + } else + return type1.getName().equals(type2.getName()) + && type1.getRequiredFields().equals(type2.getRequiredFields()) + && type1.getOptionalFields().equals(type2.getOptionalFields()) + && type1.getSecondaryOptionalFields().equals(type2.getSecondaryOptionalFields()); + } + public static boolean isExclusiveBibLatex(String type) { return filterEntryTypesNames(BibLatexEntryTypes.ALL, isNotIncludedIn(BibtexEntryTypes.ALL)).contains(type.toLowerCase()); } 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 a2b40d763d2..919eea7ca74 100644 --- a/src/main/java/net/sf/jabref/model/database/BibDatabaseMode.java +++ b/src/main/java/net/sf/jabref/model/database/BibDatabaseMode.java @@ -34,19 +34,6 @@ public BibDatabaseMode getOppositeMode() { } } - /** - * Returns the {@link BibDatabaseMode} from a given boolean. - * - * @return BIBLATEX if isBibLatex is true, else BIBTEX - */ - public static BibDatabaseMode fromPreference(boolean isBibLatex) { - if (isBibLatex) { - return BIBLATEX; - } else { - return BIBTEX; - } - } - /** * Returns the {@link BibDatabaseMode} that equals the given string. The use of capital and small letters * in the string doesn't matter.If neither "bibtex" nor "biblatex" is the given string, then an 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 70b1d217523..2960123a1b8 100644 --- a/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java +++ b/src/main/java/net/sf/jabref/model/entry/IEEETranEntryTypes.java @@ -2,6 +2,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; /** * This class represents all supported IEEETran entry types. @@ -113,4 +114,8 @@ public String getName() { }; public static final List ALL = Arrays.asList(ELECTRONIC, IEEETRANBSTCTL, PERIODICAL, PATENT, STANDARD); + + public static Optional getType(String name) { + return ALL.stream().filter(e -> e.getName().equalsIgnoreCase(name)).findFirst(); + } } diff --git a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java index d9889559236..65af1ed9661 100644 --- a/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/preferences/JabRefPreferences.java @@ -83,6 +83,8 @@ public class JabRefPreferences { private static final Log LOGGER = LogFactory.getLog(JabRefPreferences.class); + private static final Class PREFS_BASE_CLASS = JabRefMain.class; + /** * HashMap that contains all preferences which are set by default */ @@ -385,15 +387,13 @@ public class JabRefPreferences { // At least in the settings, not in the implementation. But having both confused the users, therefore, having activated both options at the same time has been disabled public static final String AUTOSYNCSPECIALFIELDSTOKEYWORDS = "autoSyncSpecialFieldsToKeywords"; - //non-default preferences - private static final String CUSTOM_TYPE_NAME = "customTypeName_"; - private static final String CUSTOM_TYPE_REQ = "customTypeReq_"; - private static final String CUSTOM_TYPE_OPT = "customTypeOpt_"; - private static final String CUSTOM_TYPE_PRIOPT = "customTypePriOpt_"; - // Prefs node for BibtexKeyPatterns public static final String BIBTEX_KEY_PATTERNS_NODE = "bibtexkeypatterns"; + // Prefs node for customized entry types + public static final String CUSTOMIZED_BIBTEX_TYPES = "customizedBibtexTypes"; + public static final String CUSTOMIZED_BIBLATEX_TYPES = "customizedBiblatexTypes"; + // Version public static final String VERSION_IGNORED_UPDATE = "versionIgnoreUpdate"; @@ -463,7 +463,7 @@ private JabRefPreferences() { } // load user preferences - prefs = Preferences.userNodeForPackage(JabRefMain.class); + prefs = Preferences.userNodeForPackage(PREFS_BASE_CLASS); SearchPreferences.putDefaults(defaults); @@ -1046,6 +1046,8 @@ private static int[] getRgb(String value) { * @throws BackingStoreException */ public void clear() throws BackingStoreException { + clearAllCustomEntryTypes(); + clearKeyPatterns(); prefs.clear(); } @@ -1079,7 +1081,7 @@ public void flush() { */ public GlobalBibtexKeyPattern getKeyPattern() { keyPattern = GlobalBibtexKeyPattern.fromPattern(get(DEFAULT_BIBTEX_KEY_PATTERN)); - Preferences pre = Preferences.userNodeForPackage(JabRefMain.class).node(BIBTEX_KEY_PATTERNS_NODE); + Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); try { String[] keys = pre.keys(); if (keys.length > 0) { @@ -1102,7 +1104,7 @@ public void putKeyPattern(GlobalBibtexKeyPattern pattern) { keyPattern = pattern; // Store overridden definitions to Preferences. - Preferences pre = Preferences.userNodeForPackage(JabRefMain.class).node(BIBTEX_KEY_PATTERNS_NODE); + Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); try { pre.clear(); // We remove all old entries. } catch (BackingStoreException ex) { @@ -1120,6 +1122,63 @@ public void putKeyPattern(GlobalBibtexKeyPattern pattern) { } } + private void clearKeyPatterns() throws BackingStoreException { + Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); + pre.clear(); + } + + public void storeCustomEntryTypes(List customEntryTypes, BibDatabaseMode bibDatabaseMode) { + Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(bibDatabaseMode); + + try { + // clear old custom types + clearCustomEntryTypes(bibDatabaseMode); + + // store current custom types + customEntryTypes.forEach(type -> prefsNode.put(type.getName(), type.getAsString())); + + prefsNode.flush(); + } catch (BackingStoreException e) { + LOGGER.info("Updating stored custom entry types failed.", e); + } + } + + public List loadCustomEntryTypes(BibDatabaseMode bibDatabaseMode) { + List storedEntryTypes = new ArrayList<>(); + Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(bibDatabaseMode); + try { + Arrays.stream(prefsNode.keys()) + .map(key -> prefsNode.get(key, null)) + .filter(Objects::nonNull) + .forEach(typeString -> CustomEntryType.parse(typeString).ifPresent(storedEntryTypes::add)); + } catch (BackingStoreException e) { + LOGGER.info("Parsing customized entry types failed.", e); + } + return storedEntryTypes; + } + + private void clearAllCustomEntryTypes() throws BackingStoreException { + for(BibDatabaseMode mode :BibDatabaseMode.values()) { + clearCustomEntryTypes(mode); + } + } + + private void clearCustomEntryTypes(BibDatabaseMode mode) throws BackingStoreException { + Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(mode); + prefsNode.clear(); + } + + private static Preferences getPrefsNodeForCustomizedEntryTypes(BibDatabaseMode mode) { + if (mode == BibDatabaseMode.BIBLATEX) { + return Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(CUSTOMIZED_BIBLATEX_TYPES); + } + if (mode == BibDatabaseMode.BIBTEX) { + return Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(CUSTOMIZED_BIBTEX_TYPES); + } + + throw new IllegalArgumentException("Unknown BibDatabaseMode: " + mode); + } + public Map getPreferences() { Map result = new HashMap<>(); try { @@ -1189,53 +1248,6 @@ private static Optional getNextUnit(Reader data) throws IOException { } } - /** - * Stores all information about the entry type in preferences, with the tag given by number. - */ - public void storeCustomEntryType(CustomEntryType tp, int number) { - String nr = String.valueOf(number); - put(CUSTOM_TYPE_NAME + nr, tp.getName()); - put(CUSTOM_TYPE_REQ + nr, tp.getRequiredFieldsString()); - List optionalFields = tp.getOptionalFields(); - putStringList(CUSTOM_TYPE_OPT + nr, optionalFields); - List primaryOptionalFields = tp.getPrimaryOptionalFields(); - putStringList(CUSTOM_TYPE_PRIOPT + nr, primaryOptionalFields); - } - - /** - * Retrieves all information about the entry type in preferences, with the tag given by number. - */ - public Optional getCustomEntryType(int number) { - String nr = String.valueOf(number); - String name = get(CUSTOM_TYPE_NAME + nr); - if (name == null) { - return Optional.empty(); - } - List req = getStringList(CUSTOM_TYPE_REQ + nr); - List opt = getStringList(CUSTOM_TYPE_OPT + nr); - List priOpt = getStringList(CUSTOM_TYPE_PRIOPT + nr); - if (priOpt.isEmpty()) { - return Optional.of(new CustomEntryType(StringUtil.capitalizeFirst(name), req, opt)); - } - List secondary = new ArrayList<>(opt); - secondary.removeAll(priOpt); - - return Optional.of(new CustomEntryType(StringUtil.capitalizeFirst(name), req, priOpt, secondary)); - - } - - /** - * Removes all information about custom entry types with tags of - * - * @param number or higher. - */ - public void purgeCustomEntryTypes(int number) { - purgeSeries(CUSTOM_TYPE_NAME, number); - purgeSeries(CUSTOM_TYPE_REQ, number); - purgeSeries(CUSTOM_TYPE_OPT, number); - purgeSeries(CUSTOM_TYPE_PRIOPT, number); - } - /** * Removes all entries keyed by prefix+number, where number is equal to or higher than the given number. * diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 9a9325fd9db..fd80e506987 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Regulærudtryk -Remember_these_entry_types?=Husk_disse_posttyper? - Remote_operation=Fjernstyring Remote_server_port=Port_til_fjernstyring @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 73e6a54ee5d..666ba058b8c 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Regulärer_Ausdruck -Remember_these_entry_types?=Diese_Eintragstypen_behalten? - Remote_operation=Externer_Zugriff Remote_server_port=Externer_Server-Port @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry=Springe_zu_Eintrag diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 98f440d6098..2aa651e2020 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=regular_expression -Remember_these_entry_types?=Remember_these_entry_types? - Remote_operation=Remote_operation Remote_server_port=Remote_server_port @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.=Could_not_find_any_bibliographic_i BibTeX_key_%0_deviates_from_generated_key_%1=BibTeX_key_%0_deviates_from_generated_key_%1 DOI_%0_is_invalid=DOI_%0_is_invalid +Select_all_customized_types_to_be_stored_in_local_preferences=Select_all_customized_types_to_be_stored_in_local_preferences +Currently_unknown=Currently\_unknown +Different_Customization,_current_settings_will_be_overwritten=Different_Customization,_current_settings_will_be_overwritten Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX=Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX Jump_to_entry=Jump_to_entry diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 08a75a346eb..5d994412a44 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Expresión_Regular -Remember_these_entry_types?=¿Recordar_estos_tipos_de_entrada? - Remote_operation=Operación_remota Remote_server_port=Puerto_remoto_del_servidor @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 32773de7f68..0b1a06452ac 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression= -Remember_these_entry_types?= - Remote_operation= Remote_server_port= @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 7e5cea95320..f0a706b8256 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Expression_régulière -Remember_these_entry_types?=Se_souvenir_de_ces_types_d'entrées_? - Remote_operation=Accès_à_distance Remote_server_port=Port_du_serveur_d'accès_à_distance @@ -2314,3 +2312,7 @@ DOI_%0_is_invalid=Le_DOI_%0_est_invalide Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry=Aller_à_cette_entrée + +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index e682a97de0e..7c9a57a28ad 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Ekspresi_reguler -Remember_these_entry_types?=Ingat_tipe_entri_ini? - Remote_operation=Penggunaan_jarak_jauh Remote_server_port=Port_server_jauh @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index f6f9654956a..8c958430032 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Espressione_regolare -Remember_these_entry_types?=Ricordare_questo_tipo_di_voce? - Remote_operation=Accesso_remoto Remote_server_port=Porta_del_server_remoto @@ -2304,13 +2302,15 @@ This_might_be_caused_by_reaching_the_traffic_limitation_of_Google_Scholar_(see_' Problem_downloading_from_%1=Problema_scaricando_da_%1 -File_directory_pattern= Update_with_bibliographic_information_from_the_web=Aggiorna_con_informazioni_bibliografiche_dal_web Could_not_find_any_bibliographic_information.=Non_ho_trovato_informazioni_bibliografiche. BibTeX_key_%0_deviates_from_generated_key_%1=Chiave_BibTeX_%0_diversa_dalla_chiave_generata_%1 DOI_%0_is_invalid=DOI_%0_non_valido - Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= +File_directory_pattern= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 9c50049dd0b..19487e7e2d3 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=正規表現 -Remember_these_entry_types?=これらの項目型を記憶しますか? - Remote_operation=リモート操作 Remote_server_port=リモートサーバーのポート @@ -2311,6 +2309,8 @@ Could_not_find_any_bibliographic_information.=文献情報を見つけること BibTeX_key_%0_deviates_from_generated_key_%1=BibTeX鍵%0は生成された鍵%1と異なります DOI_%0_is_invalid=DOI_%0は有効ではありません - Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry=項目へジャンプ +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 50532a4bcfb..c79f8e43cb0 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Regular_Expression -Remember_these_entry_types?=Deze_entry_types_behouden? - Remote_operation=Externe_operatie Remote_server_port=Externe_server_poort @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 5db05fa81e8..5f701280821 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Regul\u00e6ruttrykk -Remember_these_entry_types?=Husk_disse_enhetstypene? - Remote_operation=Fjernstyring Remote_server_port=Port_for_fjernstyring @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 0036fbb3167..dfe7fcc2f24 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Expressão_regular -Remember_these_entry_types?=Lembrar_destes_tipos_de_referências? - Remote_operation=Operação_remota Remote_server_port=Remover_porta_do_servidor @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 37e3ba4df4b..b7db4c20d1b 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Регулярное_выражение -Remember_these_entry_types?=Запомнить_эти_типы_записей? - Remote_operation=Операции_удаленного_подключения Remote_server_port=Порт_сервера_удаленного_подключения @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 6184bcf1183..060fc156ad1 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=reguljärt_uttryck -Remember_these_entry_types?=Kom_ihåg_dessa_posttyper? - Remote_operation=Fjärrstyrning Remote_server_port=Port_på_fjärrserver @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index b9c794680ad..e88fe5976ef 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Düzenli_İfade -Remember_these_entry_types?=Bu_girdi_türlerini_anımsa? - Remote_operation=Uzak_işlem Remote_server_port=Uzak_sunucu_bağlantı_noktası @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 16a298fb146..dafd26417a8 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=Biểu_thức_chính_tắc -Remember_these_entry_types?=Nhớ_các_kiểu_mục_này? - Remote_operation=Lệnh_từ_xa Remote_server_port=Cổng_máy_chủ_từ_xa @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index 36e208f9e4c..a7e80470e1e 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -1006,8 +1006,6 @@ Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and regular_expression=正则表达式 -Remember_these_entry_types?=记住这些记录类型? - Remote_operation=远程操作 Remote_server_port=远程服务器端口 @@ -2311,6 +2309,9 @@ Could_not_find_any_bibliographic_information.= BibTeX_key_%0_deviates_from_generated_key_%1= DOI_%0_is_invalid= +Select_all_customized_types_to_be_stored_in_local_preferences= +Currently_unknown= +Different_Customization,_current_settings_will_be_overwritten= Entry_type_%0_is_only_defined_for_Biblatex_but_not_for_BibTeX= Jump_to_entry= diff --git a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java deleted file mode 100644 index 1705da3c5d6..00000000000 --- a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibLatex.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.sf.jabref.logic.bibtex; - -import java.util.Optional; - -import net.sf.jabref.model.EntryTypes; -import net.sf.jabref.model.database.BibDatabaseMode; -import net.sf.jabref.model.entry.BibLatexEntryTypes; -import net.sf.jabref.model.entry.BibtexEntryTypes; - -import org.junit.Ignore; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class EntryTypesTestBibLatex { - @Test - @Ignore("This fails of unknown reasons - will be fixed with https://github.com/JabRef/jabref/pull/2331") - public void testBibLatexMode() { - // BibLatex mode - assertEquals(BibLatexEntryTypes.ARTICLE, EntryTypes.getType("article", BibDatabaseMode.BIBLATEX).get()); - assertEquals(Optional.empty(), EntryTypes.getType("aaaaarticle", BibDatabaseMode.BIBLATEX)); - assertEquals(Optional.empty(), EntryTypes.getStandardType("aaaaarticle", BibDatabaseMode.BIBLATEX)); - assertEquals(34, EntryTypes.getAllValues(BibDatabaseMode.BIBLATEX).size()); - assertEquals(34, EntryTypes.getAllTypes(BibDatabaseMode.BIBLATEX).size()); - - EntryTypes.removeType("article", BibDatabaseMode.BIBLATEX); - // Should not be possible to remove a standard type - assertEquals(BibLatexEntryTypes.ARTICLE, EntryTypes.getType("article", BibDatabaseMode.BIBLATEX).get()); - } - - @Test - public void defaultType() { - assertEquals(BibLatexEntryTypes.MISC, EntryTypes.getTypeOrDefault("unknowntype", BibDatabaseMode.BIBLATEX)); - } - - @Test - public void detectExclusiveBiblatexType() { - assertTrue(EntryTypes.isExclusiveBibLatex(BibLatexEntryTypes.MVBOOK.getName())); - } - - @Test - public void detectUndistinguishableAsBibtex() { - assertFalse(EntryTypes.isExclusiveBibLatex(BibtexEntryTypes.ARTICLE.getName())); - assertFalse(EntryTypes.isExclusiveBibLatex(BibLatexEntryTypes.ARTICLE.getName())); - } - - @Test - public void detectUnknownTypeAsBibtex() { - assertFalse(EntryTypes.isExclusiveBibLatex("unknowntype")); - } -} diff --git a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java b/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java deleted file mode 100644 index df8f00a1567..00000000000 --- a/src/test/java/net/sf/jabref/logic/bibtex/EntryTypesTestBibtex.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.sf.jabref.logic.bibtex; - -import java.util.ArrayList; -import java.util.Optional; -import java.util.stream.Collectors; - -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 org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - - -public class EntryTypesTestBibtex { - - @Test - public void testBibtexMode() { - // Bibtex mode - 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("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 - ArrayList requiredFields = new ArrayList<>(BibtexEntryTypes.ARTICLE.getRequiredFields()); - requiredFields.add("specialfield"); - - CustomEntryType newArticle = new CustomEntryType("article", requiredFields, - BibtexEntryTypes.ARTICLE.getOptionalFields()); - - EntryTypes.addOrModifyCustomEntryType(newArticle); - // Should not be the same any more - assertNotEquals(BibtexEntryTypes.ARTICLE, EntryTypes.getType("article", BibDatabaseMode.BIBTEX).get()); - - // Remove the custom "article" entry type, which should restore the original - EntryTypes.removeType("article", BibDatabaseMode.BIBTEX); - // Should not be possible to remove a standard type - assertEquals(BibtexEntryTypes.ARTICLE, EntryTypes.getType("article", BibDatabaseMode.BIBTEX).get()); - } - - @Test - public void defaultType() { - assertEquals(BibtexEntryTypes.MISC, EntryTypes.getTypeOrDefault("unknowntype", BibDatabaseMode.BIBTEX)); - } - -} 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 3e776f202ad..87c310328e3 100644 --- a/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/net/sf/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -244,7 +244,7 @@ public void writeStringAndEncoding() throws Exception { @Test public void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws Exception { try { - EntryTypes.addOrModifyCustomEntryType(new CustomEntryType("customizedType", "required", "optional")); + EntryTypes.addOrModifyCustomEntryType(new CustomEntryType("customizedType", "required", "optional"), BibDatabaseMode.BIBTEX); BibEntry entry = new BibEntry(); entry.setType("customizedType"); database.insertEntry(entry); diff --git a/src/test/java/net/sf/jabref/model/EntryTypesTest.java b/src/test/java/net/sf/jabref/model/EntryTypesTest.java new file mode 100644 index 00000000000..070f678eea7 --- /dev/null +++ b/src/test/java/net/sf/jabref/model/EntryTypesTest.java @@ -0,0 +1,160 @@ +package net.sf.jabref.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import net.sf.jabref.model.database.BibDatabaseMode; +import net.sf.jabref.model.entry.BibLatexEntryTypes; +import net.sf.jabref.model.entry.BibtexEntryTypes; +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.IEEETranEntryTypes; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +@RunWith(Parameterized.class) +public class EntryTypesTest { + + private BibDatabaseMode mode; + private BibDatabaseMode otherMode; + private EntryType standardArticleType; + private EntryType defaultType; + + private CustomEntryType newCustomType; + private CustomEntryType overwrittenStandardType; + + public EntryTypesTest(BibDatabaseMode mode) { + this.mode = mode; + this.otherMode = (mode == BibDatabaseMode.BIBLATEX) ? BibDatabaseMode.BIBTEX : BibDatabaseMode.BIBLATEX; + this.standardArticleType = (mode == BibDatabaseMode.BIBLATEX) ? BibLatexEntryTypes.ARTICLE : BibtexEntryTypes.ARTICLE; + this.defaultType = (mode == BibDatabaseMode.BIBLATEX) ? BibLatexEntryTypes.MISC : BibtexEntryTypes.MISC; + } + + @Parameterized.Parameters + public static Object[] data() { + return new Object[] { BibDatabaseMode.BIBTEX, BibDatabaseMode.BIBLATEX }; + } + + @Before + public void setUp() { + newCustomType = new CustomEntryType("customType", "required", "optional"); + List newRequiredFields = new ArrayList<>(BibtexEntryTypes.ARTICLE.getRequiredFields()); + newRequiredFields.add("additional"); + overwrittenStandardType = new CustomEntryType(BibtexEntryTypes.ARTICLE.getName(), newRequiredFields, + Collections.singletonList("optional")); + } + + @After + public void tearDown() { + EntryTypes.removeAllCustomEntryTypes(); + } + + @Test + public void assertDefaultValuesBibtex() { + List sortedDefaultType = new ArrayList<>(BibtexEntryTypes.ALL); + sortedDefaultType.addAll(IEEETranEntryTypes.ALL); + Collections.sort(sortedDefaultType); + + List sortedEntryTypes = new ArrayList<>(EntryTypes.getAllValues(BibDatabaseMode.BIBTEX)); + Collections.sort(sortedEntryTypes); + + assertEquals(sortedDefaultType, sortedEntryTypes); + } + + @Test + public void assertDefaultValuesBiblatex() { + List sortedDefaultType = new ArrayList<>(BibLatexEntryTypes.ALL); + Collections.sort(sortedDefaultType); + + List sortedEntryTypes = new ArrayList<>(EntryTypes.getAllValues(BibDatabaseMode.BIBLATEX)); + Collections.sort(sortedEntryTypes); + + assertEquals(sortedDefaultType, sortedEntryTypes); + } + + @Test + public void unknownTypeIsNotFound() { + assertEquals(Optional.empty(), EntryTypes.getType("aaaaarticle", mode)); + assertEquals(Optional.empty(), EntryTypes.getStandardType("aaaaarticle", mode)); + } + + @Test + public void unknownTypeIsConvertedToMiscByGetTypeOrDefault() { + assertEquals(defaultType, EntryTypes.getTypeOrDefault("unknowntype", mode)); + } + + @Test + public void registerCustomEntryType() { + EntryTypes.addOrModifyCustomEntryType(newCustomType, mode); + assertEquals(Optional.of(newCustomType), EntryTypes.getType("customType", mode)); + } + + @Test + public void registeredCustomEntryTypeIsContainedInListOfCustomizedEntryTypes() { + EntryTypes.addOrModifyCustomEntryType(newCustomType, mode); + assertEquals(Arrays.asList(newCustomType), EntryTypes.getAllCustomTypes(mode)); + } + + @Test + public void registerCustomEntryTypeDoesNotAffectOtherMode() { + EntryTypes.addOrModifyCustomEntryType(newCustomType, mode); + assertFalse(EntryTypes.getAllValues(otherMode).contains(newCustomType)); + } + + @Test + public void overwriteCustomEntryTypeFields() { + EntryTypes.addOrModifyCustomEntryType(newCustomType, mode); + CustomEntryType newCustomEntryTypeAuthorRequired = new CustomEntryType("customType", FieldName.AUTHOR, "optional"); + EntryTypes.addOrModifyCustomEntryType(newCustomEntryTypeAuthorRequired, mode); + assertEquals(Optional.of(newCustomEntryTypeAuthorRequired), EntryTypes.getType("customType", mode)); + } + + @Test + public void overwriteStandardTypeRequiredFields() { + EntryTypes.addOrModifyCustomEntryType(overwrittenStandardType, mode); + assertEquals(Optional.of(overwrittenStandardType), EntryTypes.getType(overwrittenStandardType.getName(), mode)); + } + + @Test + public void registeredCustomizedStandardEntryTypeIsContainedInListOfCustomizedEntryTypes() { + EntryTypes.addOrModifyCustomEntryType(overwrittenStandardType, mode); + assertEquals(Arrays.asList(overwrittenStandardType), EntryTypes.getAllModifiedStandardTypes(mode)); + } + + + @Test + public void standardTypeIsStillAcessibleIfOverwritten() { + EntryTypes.addOrModifyCustomEntryType(overwrittenStandardType, mode); + assertEquals(Optional.of(standardArticleType), EntryTypes.getStandardType(overwrittenStandardType.getName(), mode)); + } + + @Test + public void standardTypeIsRestoredAfterDeletionOfOverwrittenType() { + EntryTypes.addOrModifyCustomEntryType(overwrittenStandardType, mode); + EntryTypes.removeType(overwrittenStandardType.getName(), mode); + assertEquals(Optional.of(standardArticleType), EntryTypes.getType(overwrittenStandardType.getName(), mode)); + } + + @Test + public void standardTypeCannotBeRemoved() { + EntryTypes.removeType(standardArticleType.getName(), mode); + assertEquals(Optional.of(standardArticleType), EntryTypes.getType(standardArticleType.getName(), mode)); + } + + @Test + public void overwriteStandardTypeRequiredFieldsDoesNotAffectOtherMode() { + EntryTypes.addOrModifyCustomEntryType(overwrittenStandardType, mode); + assertFalse(EntryTypes.getAllValues(otherMode).contains(overwrittenStandardType)); + } +}