From 5e8a4d5136ded988e1514e11d8cb6ff81467b5c1 Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Sat, 2 Sep 2023 22:34:44 +0200
Subject: [PATCH 1/4] Fix mixup with YAML tags (#10287)
---
.github/workflows/deployment-arm64.yml | 4 ++--
.github/workflows/deployment.yml | 12 ++++++------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/deployment-arm64.yml b/.github/workflows/deployment-arm64.yml
index d70fb31c04e2..38693c6fd8b5 100644
--- a/.github/workflows/deployment-arm64.yml
+++ b/.github/workflows/deployment-arm64.yml
@@ -163,7 +163,7 @@ jobs:
xcrun notarytool submit build/distribution/JabRef-${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}-arm64.pkg --keychain-profile "notarytool-profile" --keychain ${{runner.temp}}/keychain/notarization.keychain --wait
xcrun stapler staple build/distribution/JabRef-${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}-arm64.pkg
- name: Upload with rsync
- if: ! startsWith(github.ref, 'refs/heads/gh-readonly-queue')
+ if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }}
shell: bash
run: |
mkdir ${{runner.temp}}/sshkey
@@ -173,7 +173,7 @@ jobs:
fi
rsync -Pavz --itemize-changes --stats --partial-dir=/tmp/partial --rsync-path="mkdir -p /var/www/builds.jabref.org/www/${{ steps.gitversion.outputs.branchName }} && rsync" -e 'ssh -p 9922 -i ~/.ssh/id_rsa' build/distribution/ jrrsync@build-upload.jabref.org:/var/www/builds.jabref.org/www/${{ steps.gitversion.outputs.branchName }}/
- name: Upload to GitHub workflow artifacts store
- if: ! startsWith(github.ref, 'refs/heads/gh-readonly-queue')
+ if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }}
uses: actions/upload-artifact@v3
with:
name: JabRef-${{ matrix.displayName }}
diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml
index d4704ae32397..c439988a2263 100644
--- a/.github/workflows/deployment.yml
+++ b/.github/workflows/deployment.yml
@@ -229,7 +229,7 @@ jobs:
rm debian-binary control.tar.* data.tar.*
mv -f jabref_${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}_amd64_repackaged.deb jabref_${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}_amd64.deb
- name: Upload to builds.jabref.org (ubuntu)
- if: (matrix.os == 'ubuntu-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (! startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
+ if: (matrix.os == 'ubuntu-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (!startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
uses: Pendect/action-rsyncer@v2.0.0
env:
DEPLOY_KEY: ${{ secrets.buildJabRefPrivateKey }}
@@ -240,13 +240,13 @@ jobs:
src: 'build/distribution/'
dest: jrrsync@build-upload.jabref.org:/var/www/builds.jabref.org/www/${{ steps.gitversion.outputs.branchName }}/
- name: Upload to GitHub workflow artifacts store (windows)
- if: (matrix.os == 'windows-latest') && (! startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
+ if: (matrix.os == 'windows-latest') && (!startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
uses: actions/upload-artifact@v3
with:
name: JabRef-${{ matrix.displayName }}
path: build/distribution
- name: Upload to GitHub workflow artifacts store (macos)
- if: (matrix.os == 'macos-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (! startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
+ if: (matrix.os == 'macos-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (!startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
uses: actions/upload-artifact@v3
with:
# tbn = to-be-notarized
@@ -307,7 +307,7 @@ jobs:
shell: bash
run: ${{ matrix.archivePortable }}
- name: Upload to GitHub workflow artifacts store
- if: (steps.checksecrets.outputs.secretspresent == 'YES') && (! startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
+ if: (steps.checksecrets.outputs.secretspresent == 'YES') && (!startsWith(github.ref, 'refs/heads/gh-readonly-queue'))
uses: actions/upload-artifact@v3
with:
name: JabRef-macOS
@@ -318,7 +318,7 @@ jobs:
name: Upload binaries on builds.jabref.org
runs-on: ubuntu-latest
needs: [build, notarize]
- if: ! startsWith(github.ref, 'refs/heads/gh-readonly-queue')
+ if: ${{ !startsWith(github.ref, 'refs/heads/gh-readonly-queue') }}
steps:
- name: Check secrets presence
id: checksecrets
@@ -353,7 +353,7 @@ jobs:
name: JabRef-windows
path: build/distribution
- name: Get macOS binaries unsigned
- if: (steps.checksecrets.outputs.secretspresent == 'YES') && (inputs.notarization == false && ! startsWith(github.ref, 'refs/tags/'))
+ if: (steps.checksecrets.outputs.secretspresent == 'YES') && (inputs.notarization == false && !startsWith(github.ref, 'refs/tags/'))
uses: actions/download-artifact@master
with:
name: JabRef-macOS-tbn
From d743f52298d40f1ef81331dcff846b31c992667c Mon Sep 17 00:00:00 2001
From: Oliver Kopp
Date: Sat, 2 Sep 2023 21:33:11 +0200
Subject: [PATCH 2/4] Fix selection of table sort order (#10250)
* Inline LOGGER.debug
* Move out work in constructor to method
* Streamline code
* Same comments
* Fix variable name
* "Flatten" SaveOrder if OrderType.TABLE
* WIP: Show diff in UI
* Make it scrollable
Co-authored-by: Christoph
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
* WIP: Try to fix content selector diff
Co-authored-by: Christoph
* Add some debugging
* Update preferences immediatly after change (and not sometime later)
* Fix serialization of SaveOrder
* Add CHANGELOG.md entry
* Fix mapping of SaveOrderConfig
* Introduce SelfContainedSaveOrder
* More SelfContainedSaveOrder
* Remove ref to PrefsService
* Compile fix
* Made OrFields NOT extending LinkedHashSet
* Fix hillarious bug
* Fixed tests
* Try to fix FieldComparators for OrFields
* Fix order of null comparisons
Refs tests of #7544
* Fix checkstyle
* Add missing equals, hashcode and toString
* Fix checkstyle
* Restore test files
* Fix OpenRewrite
* Fix modernizer
* Update CHANGELOG.md
* Fix NPE
---------
Co-authored-by: Christoph
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
---
.gitignore | 2 +
CHANGELOG.md | 2 +
src/main/java/org/jabref/gui/JabRefFrame.java | 4 +-
src/main/java/org/jabref/gui/LibraryTab.java | 6 +-
.../autosaveandbackup/AutosaveManager.java | 2 +-
.../autosaveandbackup/BackupManager.java | 42 ++++++++---
.../MetadataChangeDetailsView.java | 23 ++++---
.../jabref/gui/dialogs/BackupUIManager.java | 2 +-
.../gui/entryeditor/RequiredFieldsTab.java | 2 +-
.../gui/exporter/SaveDatabaseAction.java | 41 ++++++++---
.../importer/actions/OpenDatabaseAction.java | 2 +-
.../ContentSelectorViewModel.java | 24 +++++++
.../org/jabref/gui/maintable/MainTable.java | 29 ++++----
.../gui/maintable/MainTableColumnModel.java | 19 +++++
.../MainTableFieldValueFormatter.java | 2 +-
.../PersistenceVisualStateTable.java | 56 ++++++++++-----
.../gui/maintable/columns/FieldColumn.java | 4 +-
.../jabref/gui/search/SearchResultsTable.java | 2 +-
.../jabref/logic/bibtex/BibEntryWriter.java | 12 ++--
.../bibtex/comparator/FieldComparator.java | 8 +--
.../logic/bibtex/comparator/MetaDataDiff.java | 69 ++++++++-----------
.../jabref/logic/crawler/StudyRepository.java | 3 +-
.../logic/exporter/BibDatabaseWriter.java | 4 +-
.../logic/exporter/ExporterFactory.java | 4 +-
.../logic/exporter/SaveConfiguration.java | 12 ++--
.../logic/exporter/TemplateExporter.java | 9 +--
.../style/OOBibStyleGetCitationMarker.java | 2 +-
.../jabref/logic/util/io/BackupFileUtil.java | 3 +-
.../model/database/event/AutosaveEvent.java | 4 +-
.../java/org/jabref/model/entry/BibEntry.java | 2 +-
.../model/entry/BibEntryTypeBuilder.java | 5 +-
.../model/entry/field/FieldFactory.java | 2 +-
.../jabref/model/entry/field/OrFields.java | 60 +++++++++++++---
.../model/metadata/ContentSelectors.java | 8 +++
.../org/jabref/model/metadata/SaveOrder.java | 20 +++---
.../metadata/SelfContainedSaveOrder.java | 27 ++++++++
.../jabref/preferences/JabRefPreferences.java | 18 ++---
.../preferences/PreferencesService.java | 3 +
src/main/resources/tinylog.properties | 1 +
.../BackupManagerDiscardedTest.java | 5 +-
.../autosaveandbackup/BackupManagerTest.java | 15 +++-
.../exporter/ExportToClipboardActionTest.java | 2 +
.../comparator/FieldComparatorTest.java | 47 ++++++++++---
.../autosaveandbackup/changes.bib | 0
.../autosaveandbackup/changes.bib.bak | 0
.../autosaveandbackup/no-autosave.bib | 0
.../autosaveandbackup/no-changes.bib | 0
.../autosaveandbackup/no-changes.bib.bak | 0
48 files changed, 419 insertions(+), 190 deletions(-)
rename src/main/java/org/jabref/{logic => gui}/autosaveandbackup/AutosaveManager.java (98%)
rename src/main/java/org/jabref/{logic => gui}/autosaveandbackup/BackupManager.java (87%)
create mode 100644 src/main/java/org/jabref/model/metadata/SelfContainedSaveOrder.java
rename src/test/java/org/jabref/{logic => gui}/autosaveandbackup/BackupManagerDiscardedTest.java (95%)
rename src/test/java/org/jabref/{logic => gui}/autosaveandbackup/BackupManagerTest.java (93%)
rename src/test/resources/org/jabref/{logic => gui}/autosaveandbackup/changes.bib (100%)
rename src/test/resources/org/jabref/{logic => gui}/autosaveandbackup/changes.bib.bak (100%)
rename src/test/resources/org/jabref/{logic => gui}/autosaveandbackup/no-autosave.bib (100%)
rename src/test/resources/org/jabref/{logic => gui}/autosaveandbackup/no-changes.bib (100%)
rename src/test/resources/org/jabref/{logic => gui}/autosaveandbackup/no-changes.bib.bak (100%)
diff --git a/.gitignore b/.gitignore
index 8722502e3402..1d3864a220b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -478,5 +478,7 @@ lib/ojdbc.jar
# do not ignore JabRef icons (they are ignored by the macos setting above)
!src/main/java/org/jabref/gui/icon
+!**/autosaveandbackup/*.bak
+
# generated during release process
CHANGELOG.html
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 157c767ab285..6088e85301e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,8 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
### Fixed
+- It is possible again to use "current table sort order" for the order of entries when saving. [#9869](https://github.com/JabRef/jabref/issues/9869)
+
### Removed
## [5.10] - 2023-09-02
diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java
index 2458b5a41273..88a37f989279 100644
--- a/src/main/java/org/jabref/gui/JabRefFrame.java
+++ b/src/main/java/org/jabref/gui/JabRefFrame.java
@@ -54,6 +54,8 @@
import org.jabref.gui.actions.ActionHelper;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.gui.actions.StandardActions;
+import org.jabref.gui.autosaveandbackup.AutosaveManager;
+import org.jabref.gui.autosaveandbackup.BackupManager;
import org.jabref.gui.auximport.NewSubLibraryAction;
import org.jabref.gui.bibtexextractor.ExtractBibtexAction;
import org.jabref.gui.citationkeypattern.GenerateCitationKeyAction;
@@ -118,8 +120,6 @@
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.DefaultTaskExecutor;
import org.jabref.gui.util.TaskExecutor;
-import org.jabref.logic.autosaveandbackup.AutosaveManager;
-import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.citationstyle.CitationStyleOutputFormat;
import org.jabref.logic.help.HelpFile;
import org.jabref.logic.importer.IdFetcher;
diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java
index 4beabbfea928..fa02d937aa5f 100644
--- a/src/main/java/org/jabref/gui/LibraryTab.java
+++ b/src/main/java/org/jabref/gui/LibraryTab.java
@@ -26,6 +26,8 @@
import org.jabref.gui.autocompleter.AutoCompletePreferences;
import org.jabref.gui.autocompleter.PersonNameSuggestionProvider;
import org.jabref.gui.autocompleter.SuggestionProviders;
+import org.jabref.gui.autosaveandbackup.AutosaveManager;
+import org.jabref.gui.autosaveandbackup.BackupManager;
import org.jabref.gui.collab.DatabaseChangeMonitor;
import org.jabref.gui.dialogs.AutosaveUiManager;
import org.jabref.gui.entryeditor.EntryEditor;
@@ -39,8 +41,6 @@
import org.jabref.gui.undo.UndoableRemoveEntries;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.DefaultTaskExecutor;
-import org.jabref.logic.autosaveandbackup.AutosaveManager;
-import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.citationstyle.CitationStyleCache;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.importer.util.FileFieldParser;
@@ -294,7 +294,7 @@ public void installAutosaveManagerAndBackupManager() {
autosaveManager.registerListener(new AutosaveUiManager(this, preferencesService, entryTypesManager));
}
if (isDatabaseReadyForBackup(bibDatabaseContext) && preferencesService.getFilePreferences().shouldCreateBackup()) {
- BackupManager.start(bibDatabaseContext, Globals.entryTypesManager, preferencesService);
+ BackupManager.start(this, bibDatabaseContext, Globals.entryTypesManager, preferencesService);
}
}
diff --git a/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java b/src/main/java/org/jabref/gui/autosaveandbackup/AutosaveManager.java
similarity index 98%
rename from src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java
rename to src/main/java/org/jabref/gui/autosaveandbackup/AutosaveManager.java
index 990da5c2db4c..72402b18dd56 100644
--- a/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java
+++ b/src/main/java/org/jabref/gui/autosaveandbackup/AutosaveManager.java
@@ -1,4 +1,4 @@
-package org.jabref.logic.autosaveandbackup;
+package org.jabref.gui.autosaveandbackup;
import java.util.HashSet;
import java.util.Set;
diff --git a/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java b/src/main/java/org/jabref/gui/autosaveandbackup/BackupManager.java
similarity index 87%
rename from src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java
rename to src/main/java/org/jabref/gui/autosaveandbackup/BackupManager.java
index e3e5805df786..616c806891ad 100644
--- a/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java
+++ b/src/main/java/org/jabref/gui/autosaveandbackup/BackupManager.java
@@ -1,4 +1,4 @@
-package org.jabref.logic.autosaveandbackup;
+package org.jabref.gui.autosaveandbackup;
import java.io.IOException;
import java.io.Writer;
@@ -19,6 +19,11 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import javafx.scene.control.TableColumn;
+
+import org.jabref.gui.LibraryTab;
+import org.jabref.gui.maintable.BibEntryTableViewModel;
+import org.jabref.gui.maintable.columns.MainTableColumn;
import org.jabref.logic.bibtex.InvalidFieldValueException;
import org.jabref.logic.exporter.AtomicFileWriter;
import org.jabref.logic.exporter.BibWriter;
@@ -31,6 +36,7 @@
import org.jabref.model.database.event.BibDatabaseContextChangedEvent;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
import org.jabref.preferences.PreferencesService;
import com.google.common.eventbus.Subscribe;
@@ -58,17 +64,19 @@ public class BackupManager {
private final ScheduledThreadPoolExecutor executor;
private final CoarseChangeFilter changeFilter;
private final BibEntryTypesManager entryTypesManager;
+ private final LibraryTab libraryTab;
// Contains a list of all backup paths
// During a write, the less recent backup file is deleted
private final Queue backupFilesQueue = new LinkedBlockingQueue<>();
private boolean needsBackup = false;
- BackupManager(BibDatabaseContext bibDatabaseContext, BibEntryTypesManager entryTypesManager, PreferencesService preferences) {
+ BackupManager(LibraryTab libraryTab, BibDatabaseContext bibDatabaseContext, BibEntryTypesManager entryTypesManager, PreferencesService preferences) {
this.bibDatabaseContext = bibDatabaseContext;
this.entryTypesManager = entryTypesManager;
this.preferences = preferences;
this.executor = new ScheduledThreadPoolExecutor(2);
+ this.libraryTab = libraryTab;
changeFilter = new CoarseChangeFilter(bibDatabaseContext);
changeFilter.registerListener(this);
@@ -96,8 +104,8 @@ static Optional getLatestBackupPath(Path originalPath, Path backupDir) {
*
* @param bibDatabaseContext Associated {@link BibDatabaseContext}
*/
- public static BackupManager start(BibDatabaseContext bibDatabaseContext, BibEntryTypesManager entryTypesManager, PreferencesService preferences) {
- BackupManager backupManager = new BackupManager(bibDatabaseContext, entryTypesManager, preferences);
+ public static BackupManager start(LibraryTab libraryTab, BibDatabaseContext bibDatabaseContext, BibEntryTypesManager entryTypesManager, PreferencesService preferences) {
+ BackupManager backupManager = new BackupManager(libraryTab, bibDatabaseContext, entryTypesManager, preferences);
backupManager.startBackupTask(preferences.getFilePreferences().getBackupDirectory());
runningInstances.add(backupManager);
return backupManager;
@@ -215,18 +223,36 @@ void performBackup(Path backupPath) {
// We opted for "while" to delete backups in case there are more than 10
while (backupFilesQueue.size() >= MAXIMUM_BACKUP_FILE_COUNT) {
- Path lessRecentBackupFile = backupFilesQueue.poll();
+ Path oldestBackupFile = backupFilesQueue.poll();
try {
- Files.delete(lessRecentBackupFile);
+ Files.delete(oldestBackupFile);
} catch (IOException e) {
- LOGGER.error("Could not delete backup file {}", lessRecentBackupFile, e);
+ LOGGER.error("Could not delete backup file {}", oldestBackupFile, e);
}
}
// code similar to org.jabref.gui.exporter.SaveDatabaseAction.saveDatabase
+ SelfContainedSaveOrder saveOrder = bibDatabaseContext
+ .getMetaData().getSaveOrder()
+ .map(so -> {
+ if (so.getOrderType() == SaveOrder.OrderType.TABLE) {
+ // We need to "flatten out" SaveOrder.OrderType.TABLE as BibWriter does not have access to preferences
+ List> sortOrder = libraryTab.getMainTable().getSortOrder();
+ return new SelfContainedSaveOrder(
+ SaveOrder.OrderType.SPECIFIED,
+ sortOrder.stream()
+ .filter(col -> col instanceof MainTableColumn>)
+ .map(column -> ((MainTableColumn>) column).getModel())
+ .flatMap(model -> model.getSortCriteria().stream())
+ .toList());
+ } else {
+ return SelfContainedSaveOrder.of(so);
+ }
+ })
+ .orElse(SaveOrder.getDefaultSaveOrder());
SaveConfiguration saveConfiguration = new SaveConfiguration()
.withMakeBackup(false)
- .withSaveOrder(bibDatabaseContext.getMetaData().getSaveOrder().orElse(SaveOrder.getDefaultSaveOrder()))
+ .withSaveOrder(saveOrder)
.withReformatOnSave(preferences.getLibraryPreferences().shouldAlwaysReformatOnSave());
Charset encoding = bibDatabaseContext.getMetaData().getEncoding().orElse(StandardCharsets.UTF_8);
diff --git a/src/main/java/org/jabref/gui/collab/metedatachange/MetadataChangeDetailsView.java b/src/main/java/org/jabref/gui/collab/metedatachange/MetadataChangeDetailsView.java
index cddcdf32e2d4..3c2a81e3e01e 100644
--- a/src/main/java/org/jabref/gui/collab/metedatachange/MetadataChangeDetailsView.java
+++ b/src/main/java/org/jabref/gui/collab/metedatachange/MetadataChangeDetailsView.java
@@ -1,6 +1,7 @@
package org.jabref.gui.collab.metedatachange;
import javafx.scene.control.Label;
+import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import org.jabref.gui.collab.DatabaseChangeDetailsView;
@@ -17,20 +18,24 @@ public MetadataChangeDetailsView(MetadataChange metadataChange, PreferencesServi
header.getStyleClass().add("sectionHeader");
container.getChildren().add(header);
- for (MetaDataDiff.Difference change : metadataChange.getMetaDataDiff().getDifferences(preferencesService)) {
- container.getChildren().add(new Label(getDifferenceString(change)));
+ for (MetaDataDiff.Difference diff : metadataChange.getMetaDataDiff().getDifferences(preferencesService)) {
+ container.getChildren().add(new Label(getDifferenceString(diff.differenceType())));
+ container.getChildren().add(new Label(diff.originalObject().toString()));
+ container.getChildren().add(new Label(diff.newObject().toString()));
}
- setLeftAnchor(container, 8d);
- setTopAnchor(container, 8d);
- setRightAnchor(container, 8d);
- setBottomAnchor(container, 8d);
+ ScrollPane scrollPane = new ScrollPane(container);
+ scrollPane.setFitToWidth(true);
+ getChildren().setAll(scrollPane);
- getChildren().setAll(container);
+ setLeftAnchor(scrollPane, 8d);
+ setTopAnchor(scrollPane, 8d);
+ setRightAnchor(scrollPane, 8d);
+ setBottomAnchor(scrollPane, 8d);
}
- private String getDifferenceString(MetaDataDiff.Difference change) {
- return switch (change) {
+ private String getDifferenceString(MetaDataDiff.DifferenceType changeType) {
+ return switch (changeType) {
case PROTECTED ->
Localization.lang("Library protection");
case GROUPS_ALTERED ->
diff --git a/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java b/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java
index e416615ad235..05ba9755db4f 100644
--- a/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java
+++ b/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java
@@ -8,13 +8,13 @@
import javafx.scene.control.ButtonType;
import org.jabref.gui.DialogService;
+import org.jabref.gui.autosaveandbackup.BackupManager;
import org.jabref.gui.backup.BackupResolverDialog;
import org.jabref.gui.collab.DatabaseChange;
import org.jabref.gui.collab.DatabaseChangeList;
import org.jabref.gui.collab.DatabaseChangeResolverFactory;
import org.jabref.gui.collab.DatabaseChangesResolverDialog;
import org.jabref.gui.util.DefaultTaskExecutor;
-import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.OpenDatabase;
import org.jabref.logic.importer.ParserResult;
diff --git a/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java b/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java
index 9034a76f0c49..cfc530c9d085 100644
--- a/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java
+++ b/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java
@@ -56,7 +56,7 @@ protected Set determineFieldsToShow(BibEntry entry) {
Set fields = new LinkedHashSet<>();
if (entryType.isPresent()) {
for (OrFields orFields : entryType.get().getRequiredFields()) {
- fields.addAll(orFields);
+ fields.addAll(orFields.getFields());
}
// Add the edit field for Bibtex-key.
fields.add(InternalField.KEY_FIELD);
diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java
index f56852c25a8b..096646fd267d 100644
--- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java
+++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java
@@ -6,6 +6,7 @@
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -13,16 +14,19 @@
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.DialogPane;
+import javafx.scene.control.TableColumn;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import org.jabref.gui.DialogService;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.LibraryTab;
+import org.jabref.gui.autosaveandbackup.AutosaveManager;
+import org.jabref.gui.autosaveandbackup.BackupManager;
+import org.jabref.gui.maintable.BibEntryTableViewModel;
+import org.jabref.gui.maintable.columns.MainTableColumn;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.FileDialogConfiguration;
-import org.jabref.logic.autosaveandbackup.AutosaveManager;
-import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.exporter.AtomicFileWriter;
import org.jabref.logic.exporter.BibDatabaseWriter;
import org.jabref.logic.exporter.BibWriter;
@@ -38,6 +42,7 @@
import org.jabref.model.database.event.ChangePropagation;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
import org.jabref.preferences.PreferencesService;
import org.slf4j.Logger;
@@ -90,11 +95,31 @@ public boolean saveAs(Path file) {
return this.saveAs(file, SaveDatabaseMode.NORMAL);
}
+ private SelfContainedSaveOrder getSaveOrder() {
+ return libraryTab.getBibDatabaseContext()
+ .getMetaData().getSaveOrder()
+ .map(so -> {
+ if (so.getOrderType() == SaveOrder.OrderType.TABLE) {
+ // We need to "flatten out" SaveOrder.OrderType.TABLE as BibWriter does not have access to preferences
+ List> sortOrder = libraryTab.getMainTable().getSortOrder();
+ return new SelfContainedSaveOrder(
+ SaveOrder.OrderType.SPECIFIED,
+ sortOrder.stream()
+ .filter(col -> col instanceof MainTableColumn>)
+ .map(column -> ((MainTableColumn>) column).getModel())
+ .flatMap(model -> model.getSortCriteria().stream())
+ .toList());
+ } else {
+ return SelfContainedSaveOrder.of(so);
+ }
+ })
+ .orElse(SaveOrder.getDefaultSaveOrder());
+ }
+
public void saveSelectedAsPlain() {
askForSavePath().ifPresent(path -> {
try {
- saveDatabase(path, true, StandardCharsets.UTF_8, BibDatabaseWriter.SaveType.PLAIN_BIBTEX,
- libraryTab.getBibDatabaseContext().getMetaData().getSaveOrder().orElse(SaveOrder.getDefaultSaveOrder()));
+ saveDatabase(path, true, StandardCharsets.UTF_8, BibDatabaseWriter.SaveType.PLAIN_BIBTEX, getSaveOrder());
frame.getFileHistory().newFile(path);
dialogService.notify(Localization.lang("Saved selected to '%0'.", path.toString()));
} catch (SaveException ex) {
@@ -211,9 +236,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) {
// Make sure to remember which encoding we used
libraryTab.getBibDatabaseContext().getMetaData().setEncoding(encoding, ChangePropagation.DO_NOT_POST_EVENT);
- // Save the database
- boolean success = saveDatabase(targetPath, false, encoding, BibDatabaseWriter.SaveType.WITH_JABREF_META_DATA,
- libraryTab.getBibDatabaseContext().getMetaData().getSaveOrder().orElse(SaveOrder.getDefaultSaveOrder()));
+ boolean success = saveDatabase(targetPath, false, encoding, BibDatabaseWriter.SaveType.WITH_JABREF_META_DATA, getSaveOrder());
if (success) {
libraryTab.getUndoManager().markUnchanged();
@@ -231,7 +254,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) {
}
}
- private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding, BibDatabaseWriter.SaveType saveType, SaveOrder saveOrder) throws SaveException {
+ private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding, BibDatabaseWriter.SaveType saveType, SelfContainedSaveOrder saveOrder) throws SaveException {
// if this code is adapted, please also adapt org.jabref.logic.autosaveandbackup.BackupManager.performBackup
SaveConfiguration saveConfiguration = new SaveConfiguration()
@@ -269,7 +292,7 @@ private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding,
}
}
- private void saveWithDifferentEncoding(Path file, boolean selectedOnly, Charset encoding, Set encodingProblems, BibDatabaseWriter.SaveType saveType, SaveOrder saveOrder) throws SaveException {
+ private void saveWithDifferentEncoding(Path file, boolean selectedOnly, Charset encoding, Set encodingProblems, BibDatabaseWriter.SaveType saveType, SelfContainedSaveOrder saveOrder) throws SaveException {
DialogPane pane = new DialogPane();
VBox vbox = new VBox();
vbox.getChildren().addAll(
diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java
index 1778074a4449..121cf109c2e5 100644
--- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java
+++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java
@@ -17,13 +17,13 @@
import org.jabref.gui.LibraryTab;
import org.jabref.gui.StateManager;
import org.jabref.gui.actions.SimpleCommand;
+import org.jabref.gui.autosaveandbackup.BackupManager;
import org.jabref.gui.dialogs.BackupUIManager;
import org.jabref.gui.menus.FileHistoryMenu;
import org.jabref.gui.shared.SharedDatabaseUIManager;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.DefaultTaskExecutor;
import org.jabref.gui.util.FileDialogConfiguration;
-import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.importer.OpenDatabase;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.l10n.Localization;
diff --git a/src/main/java/org/jabref/gui/libraryproperties/contentselectors/ContentSelectorViewModel.java b/src/main/java/org/jabref/gui/libraryproperties/contentselectors/ContentSelectorViewModel.java
index a397170c92ba..db23506e8fd2 100644
--- a/src/main/java/org/jabref/gui/libraryproperties/contentselectors/ContentSelectorViewModel.java
+++ b/src/main/java/org/jabref/gui/libraryproperties/contentselectors/ContentSelectorViewModel.java
@@ -5,6 +5,7 @@
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -67,12 +68,35 @@ public void setValues() {
@Override
public void storeSettings() {
List metaDataFields = metaData.getContentSelectors().getFieldsWithSelectors();
+
+ if (isDefaultMap(fieldKeywordsMap)) {
+ Iterator iterator = metaData.getContentSelectors().getContentSelectors().iterator();
+ while (iterator.hasNext()) {
+ metaData.clearContentSelectors(iterator.next().getField());
+ }
+ }
+
fieldKeywordsMap.forEach((field, keywords) -> updateMetaDataContentSelector(metaDataFields, field, keywords));
List fieldNamesToRemove = filterFieldsToRemove();
fieldNamesToRemove.forEach(metaData::clearContentSelectors);
}
+ private boolean isDefaultMap(Map> fieldKeywordsMap) {
+ if (fieldKeywordsMap.size() != DEFAULT_FIELD_NAMES.size()) {
+ return false;
+ }
+ for (Field field : DEFAULT_FIELD_NAMES) {
+ if (!fieldKeywordsMap.containsKey(field)) {
+ return false;
+ }
+ if (!fieldKeywordsMap.get(field).isEmpty()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public ListProperty getFieldNamesBackingList() {
return fields;
}
diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java
index ee5242099cae..10f9f68022e0 100644
--- a/src/main/java/org/jabref/gui/maintable/MainTable.java
+++ b/src/main/java/org/jabref/gui/maintable/MainTable.java
@@ -148,25 +148,15 @@ public MainTable(MainTableDataModel model,
this.getSortOrder().clear();
- /* KEEP for debugging purposes
- for (var colModel : mainTablePreferences.getColumnPreferences().getColumnSortOrder()) {
- for (var col : this.getColumns()) {
- var tablecColModel = ((MainTableColumn>) col).getModel();
- if (tablecColModel.equals(colModel)) {
- LOGGER.debug("Adding sort order for col {} ", col);
- this.getSortOrder().add(col);
- break;
- }
- }
- }
- */
-
mainTablePreferences.getColumnPreferences().getColumnSortOrder().forEach(columnModel ->
this.getColumns().stream()
.map(column -> (MainTableColumn>) column)
.filter(column -> column.getModel().equals(columnModel))
.findFirst()
- .ifPresent(column -> this.getSortOrder().add(column)));
+ .ifPresent(column -> {
+ LOGGER.debug("Adding sort order for col {} ", column);
+ this.getSortOrder().add(column);
+ }));
if (mainTablePreferences.getResizeColumnsToFit()) {
this.setColumnResizePolicy(new SmartConstrainedResizePolicy());
@@ -182,7 +172,7 @@ public MainTable(MainTableDataModel model,
this.getStylesheets().add(MainTable.class.getResource("MainTable.css").toExternalForm());
// Store visual state
- new PersistenceVisualStateTable(this, mainTablePreferences.getColumnPreferences());
+ new PersistenceVisualStateTable(this, mainTablePreferences.getColumnPreferences()).addListeners();
setupKeyBindings(keyBindingRepository);
@@ -202,6 +192,7 @@ public MainTable(MainTableDataModel model,
libraryTab.getUndoManager(),
dialogService,
stateManager);
+
// Enable the header right-click menu.
new MainTableHeaderContextMenu(this, rightClickMenuFactory).show(true);
}
@@ -212,7 +203,6 @@ public MainTable(MainTableDataModel model,
* @param sortedColumn The sorted column in {@link MainTable}
* @param keyEvent The pressed character
*/
-
private void jumpToSearchKey(TableColumn sortedColumn, KeyEvent keyEvent) {
if ((keyEvent.getCharacter() == null) || (sortedColumn == null)) {
return;
@@ -494,4 +484,11 @@ private Optional findEntry(BibEntry entry) {
.filter(viewModel -> viewModel.getEntry().equals(entry))
.findFirst();
}
+
+ public static List toColumnModels(List> columns) {
+ return columns.stream()
+ .filter(col -> col instanceof MainTableColumn>)
+ .map(column -> ((MainTableColumn>) column).getModel())
+ .collect(Collectors.toList());
+ }
}
diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java
index 5ff872c14260..77bcecaf7a1a 100644
--- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java
+++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java
@@ -1,6 +1,7 @@
package org.jabref.gui.maintable;
import java.util.EnumSet;
+import java.util.List;
import java.util.Objects;
import javafx.beans.property.DoubleProperty;
@@ -15,6 +16,7 @@
import org.jabref.gui.util.FieldsUtil;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.field.FieldFactory;
+import org.jabref.model.metadata.SaveOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -142,6 +144,8 @@ public String getDisplayName() {
|| (typeProperty.getValue() == Type.INDEX)) {
return typeProperty.getValue().getDisplayName();
} else {
+ // In case an OrField is used, `FieldFactory.parseField` returns UnknownField, which leads to
+ // "author/editor(Custom)" instead of "author/editor" in the output
return FieldsUtil.getNameWithType(FieldFactory.parseField(qualifierProperty.getValue()));
}
}
@@ -166,6 +170,21 @@ public ObjectProperty sortTypeProperty() {
return sortTypeProperty;
}
+ /**
+ * Returns a list of sort cirteria based on the fields the current column displays.
+ * In case it is single field, a single SortCriterion is returned.
+ * In case of multiple fields, for each field, there is a SortCriterion contained in the list.
+ *
+ * Implementation reason: We want to have SortCriterion handle a single field, because the UI allows for handling
+ * "plain" fields only.
+ */
+ public List getSortCriteria() {
+ boolean descending = getSortType() == TableColumn.SortType.DESCENDING;
+ return FieldFactory.parseOrFields(getQualifier()).getFields().stream()
+ .map(field -> new SaveOrder.SortCriterion(field, descending))
+ .toList();
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/src/main/java/org/jabref/gui/maintable/MainTableFieldValueFormatter.java b/src/main/java/org/jabref/gui/maintable/MainTableFieldValueFormatter.java
index bb04a6775f43..33841527a34f 100644
--- a/src/main/java/org/jabref/gui/maintable/MainTableFieldValueFormatter.java
+++ b/src/main/java/org/jabref/gui/maintable/MainTableFieldValueFormatter.java
@@ -33,7 +33,7 @@ public MainTableFieldValueFormatter(NameDisplayPreferences nameDisplayPreference
* @return The formatted name field.
*/
public String formatFieldsValues(final OrFields fields, final BibEntry entry) {
- for (Field field : fields) {
+ for (Field field : fields.getFields()) {
if (field.getProperties().contains(FieldProperty.PERSON_NAMES) && (displayStyle != DisplayStyle.AS_IS)) {
Optional name = entry.getResolvedFieldOrAlias(field, bibDatabase);
diff --git a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java
index eed6c6081241..e5b1178f1a00 100644
--- a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java
+++ b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java
@@ -1,55 +1,73 @@
package org.jabref.gui.maintable;
+import java.util.List;
import java.util.stream.Collectors;
import javafx.beans.InvalidationListener;
+import javafx.collections.ListChangeListener;
+import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import org.jabref.gui.maintable.columns.MainTableColumn;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Keep track of changes made to the columns (reordering, resorting, resizing).
*/
public class PersistenceVisualStateTable {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PersistenceVisualStateTable.class);
+
protected final TableView table;
protected final ColumnPreferences preferences;
- public PersistenceVisualStateTable(final TableView table, ColumnPreferences preferences) {
+ public PersistenceVisualStateTable(TableView table, ColumnPreferences preferences) {
this.table = table;
this.preferences = preferences;
+ }
+ public void addListeners() {
table.getColumns().addListener((InvalidationListener) obs -> updateColumns());
- table.getSortOrder().addListener((InvalidationListener) obs -> updateSortOrder());
+ table.getSortOrder().addListener((ListChangeListener super TableColumn>) obs -> updateSortOrder());
// As we store the ColumnModels of the MainTable, we need to add the listener to the ColumnModel properties,
// since the value is bound to the model after the listener to the column itself is called.
- table.getColumns().forEach(col ->
- ((MainTableColumn>) col).getModel().widthProperty().addListener(obs -> updateColumns()));
- table.getColumns().forEach(col ->
- ((MainTableColumn>) col).getModel().sortTypeProperty().addListener(obs -> updateColumns()));
+
+ table.getColumns().stream()
+ .map(col -> ((MainTableColumn>) col).getModel())
+ .forEach(model -> {
+ model.widthProperty().addListener(obs -> updateColumns());
+ model.sortTypeProperty().addListener(obs -> updateColumns());
+ });
}
/**
- * Stores shown columns, their width and their sortType in preferences.
+ * Stores shown columns, their width and their {@link TableColumn.SortType} in preferences.
+ * The conversion to the "real" string in the preferences is made at
+ * {@link org.jabref.preferences.JabRefPreferences#getColumnSortTypesAsStringList(ColumnPreferences)}
*/
private void updateColumns() {
- preferences.setColumns(
- table.getColumns().stream()
- .filter(col -> col instanceof MainTableColumn>)
- .map(column -> ((MainTableColumn>) column).getModel())
- .collect(Collectors.toList()));
+ LOGGER.debug("Updating columns");
+ preferences.setColumns(toList(table.getColumns()));
}
/**
- * Stores the SortOrder of the Table in the preferences. Cannot be combined with updateColumns, because JavaFX
- * would provide just an empty list for the sort order on other changes.
+ * Stores the SortOrder of the Table in the preferences. This includes {@link TableColumn.SortType}.
+ *
+ * Cannot be combined with updateColumns, because JavaFX would provide just an empty list for the sort order
+ * on other changes.
*/
private void updateSortOrder() {
- preferences.setColumnSortOrder(
- table.getSortOrder().stream()
- .filter(col -> col instanceof MainTableColumn>)
- .map(column -> ((MainTableColumn>) column).getModel())
- .collect(Collectors.toList()));
+ LOGGER.debug("Updating sort order");
+ preferences.setColumnSortOrder(toList(table.getSortOrder()));
+ }
+
+ private List toList(List> columns) {
+ return columns.stream()
+ .filter(col -> col instanceof MainTableColumn>)
+ .map(column -> ((MainTableColumn>) column).getModel())
+ .collect(Collectors.toList());
}
}
diff --git a/src/main/java/org/jabref/gui/maintable/columns/FieldColumn.java b/src/main/java/org/jabref/gui/maintable/columns/FieldColumn.java
index e1b8b1c1ff9e..698e8e168953 100644
--- a/src/main/java/org/jabref/gui/maintable/columns/FieldColumn.java
+++ b/src/main/java/org/jabref/gui/maintable/columns/FieldColumn.java
@@ -31,9 +31,9 @@ public FieldColumn(MainTableColumnModel model) {
.withText(text -> text)
.install(this);
- if (fields.size() == 1) {
+ if (fields.hasExactlyOne()) {
// comparator can't parse more than one value
- Field field = fields.stream().collect(MoreCollectors.onlyElement());
+ Field field = fields.getFields().stream().collect(MoreCollectors.onlyElement());
if ((field instanceof UnknownField) || field.isNumeric()) {
this.setComparator(new NumericFieldComparator());
diff --git a/src/main/java/org/jabref/gui/search/SearchResultsTable.java b/src/main/java/org/jabref/gui/search/SearchResultsTable.java
index bfe8aa3d84d3..5d839d2a4a1e 100644
--- a/src/main/java/org/jabref/gui/search/SearchResultsTable.java
+++ b/src/main/java/org/jabref/gui/search/SearchResultsTable.java
@@ -66,7 +66,7 @@ public SearchResultsTable(SearchResultsTableDataModel model,
this.getStylesheets().add(MainTable.class.getResource("MainTable.css").toExternalForm());
// Store visual state
- new PersistenceVisualStateTable(this, preferencesService.getSearchDialogColumnPreferences());
+ new PersistenceVisualStateTable(this, preferencesService.getSearchDialogColumnPreferences()).addListeners();
database.getDatabase().registerListener(this);
}
diff --git a/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java b/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java
index 7cec02d2a491..663fa3e3fee6 100644
--- a/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java
+++ b/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java
@@ -24,6 +24,7 @@
import org.jabref.model.entry.field.BibField;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.InternalField;
+import org.jabref.model.entry.field.OrFields;
import org.jabref.model.strings.StringUtil;
import org.slf4j.LoggerFactory;
@@ -103,11 +104,12 @@ private void writeRequiredFieldsFirstRemainingFieldsSecond(BibEntry entry, BibWr
if (type.isPresent()) {
// Write required fields first
List requiredFields = type.get()
- .getRequiredFields()
- .stream()
- .flatMap(Collection::stream)
- .sorted(Comparator.comparing(Field::getName))
- .collect(Collectors.toList());
+ .getRequiredFields()
+ .stream()
+ .map(OrFields::getFields)
+ .flatMap(Collection::stream)
+ .sorted(Comparator.comparing(Field::getName))
+ .collect(Collectors.toList());
for (Field field : requiredFields) {
writeField(entry, out, field, indent);
diff --git a/src/main/java/org/jabref/logic/bibtex/comparator/FieldComparator.java b/src/main/java/org/jabref/logic/bibtex/comparator/FieldComparator.java
index d8d897eb1d32..42f86e0d78d2 100644
--- a/src/main/java/org/jabref/logic/bibtex/comparator/FieldComparator.java
+++ b/src/main/java/org/jabref/logic/bibtex/comparator/FieldComparator.java
@@ -73,7 +73,7 @@ private FieldType determineFieldType() {
}
private String getFieldValue(BibEntry entry) {
- for (Field aField : fields) {
+ for (Field aField : fields.getFields()) {
Optional o = entry.getFieldOrAliasLatexFree(aField);
if (o.isPresent()) {
return o.get();
@@ -92,8 +92,6 @@ public int compare(BibEntry e1, BibEntry e2) {
f1 = e1.getType().getDisplayName();
f2 = e2.getType().getDisplayName();
} else {
- // If the field is author or editor, we rearrange names so they are
- // sorted according to last name.
f1 = getFieldValue(e1);
f2 = getFieldValue(e2);
}
@@ -102,9 +100,9 @@ public int compare(BibEntry e1, BibEntry e2) {
if ((f1 == null) && (f2 == null)) {
return 0;
} else if (f1 == null) {
- return multiplier;
- } else if (f2 == null) {
return -multiplier;
+ } else if (f2 == null) {
+ return +multiplier;
}
// Now we know that both f1 and f2 are != null
diff --git a/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java b/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java
index a18058625084..5420ef97391d 100644
--- a/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java
+++ b/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java
@@ -1,6 +1,7 @@
package org.jabref.logic.bibtex.comparator;
-import java.util.EnumSet;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -8,7 +9,7 @@
import org.jabref.preferences.PreferencesService;
public class MetaDataDiff {
- public enum Difference {
+ public enum DifferenceType {
PROTECTED,
GROUPS_ALTERED,
ENCODING,
@@ -23,6 +24,9 @@ public enum Difference {
CONTENT_SELECTOR
}
+ public record Difference(DifferenceType differenceType, Object originalObject, Object newObject) {
+ }
+
private final Optional groupDiff;
private final MetaData originalMetaData;
private final MetaData newMetaData;
@@ -41,50 +45,31 @@ public static Optional compare(MetaData originalMetaData, MetaData
}
}
+ private void addToListIfDiff(List changes, DifferenceType differenceType, Object originalObject, Object newObject) {
+ if (!Objects.equals(originalObject, newObject)) {
+ changes.add(new Difference(differenceType, originalObject, newObject));
+ }
+ }
+
/**
* Should be kept in sync with {@link MetaData#equals(Object)}
*/
- public EnumSet getDifferences(PreferencesService preferences) {
- EnumSet changes = EnumSet.noneOf(Difference.class);
-
- if (originalMetaData.isProtected() != newMetaData.isProtected()) {
- changes.add(Difference.PROTECTED);
- }
- if (!Objects.equals(originalMetaData.getGroups(), newMetaData.getGroups())) {
- changes.add(Difference.GROUPS_ALTERED);
- }
- if (!Objects.equals(originalMetaData.getEncoding(), newMetaData.getEncoding())) {
- changes.add(Difference.ENCODING);
- }
- if (!Objects.equals(originalMetaData.getSaveOrder(), newMetaData.getSaveOrder())) {
- changes.add(Difference.SAVE_SORT_ORDER);
- }
- if (!Objects.equals(
+ public List getDifferences(PreferencesService preferences) {
+ List changes = new ArrayList<>();
+ addToListIfDiff(changes, DifferenceType.PROTECTED, originalMetaData.isProtected(), newMetaData.isProtected());
+ addToListIfDiff(changes, DifferenceType.GROUPS_ALTERED, originalMetaData.getGroups(), newMetaData.getGroups());
+ addToListIfDiff(changes, DifferenceType.ENCODING, originalMetaData.getEncoding(), newMetaData.getEncoding());
+ addToListIfDiff(changes, DifferenceType.SAVE_SORT_ORDER, originalMetaData.getSaveOrder(), newMetaData.getSaveOrder());
+ addToListIfDiff(changes, DifferenceType.KEY_PATTERNS,
originalMetaData.getCiteKeyPattern(preferences.getCitationKeyPatternPreferences().getKeyPattern()),
- newMetaData.getCiteKeyPattern(preferences.getCitationKeyPatternPreferences().getKeyPattern()))) {
- changes.add(Difference.KEY_PATTERNS);
- }
- if (!Objects.equals(originalMetaData.getUserFileDirectories(), newMetaData.getUserFileDirectories())) {
- changes.add(Difference.USER_FILE_DIRECTORY);
- }
- if (!Objects.equals(originalMetaData.getLatexFileDirectories(), newMetaData.getLatexFileDirectories())) {
- changes.add(Difference.LATEX_FILE_DIRECTORY);
- }
- if (!Objects.equals(originalMetaData.getDefaultCiteKeyPattern(), newMetaData.getDefaultCiteKeyPattern())) {
- changes.add(Difference.DEFAULT_KEY_PATTERN);
- }
- if (!Objects.equals(originalMetaData.getSaveActions(), newMetaData.getSaveActions())) {
- changes.add(Difference.SAVE_ACTIONS);
- }
- if (!originalMetaData.getMode().equals(newMetaData.getMode())) {
- changes.add(Difference.MODE);
- }
- if (!Objects.equals(originalMetaData.getDefaultFileDirectory(), newMetaData.getDefaultFileDirectory())) {
- changes.add(Difference.GENERAL_FILE_DIRECTORY);
- }
- if (!Objects.equals(originalMetaData.getContentSelectors(), newMetaData.getContentSelectors())) {
- changes.add(Difference.CONTENT_SELECTOR);
- }
+ newMetaData.getCiteKeyPattern(preferences.getCitationKeyPatternPreferences().getKeyPattern()));
+ addToListIfDiff(changes, DifferenceType.USER_FILE_DIRECTORY, originalMetaData.getUserFileDirectories(), newMetaData.getUserFileDirectories());
+ addToListIfDiff(changes, DifferenceType.LATEX_FILE_DIRECTORY, originalMetaData.getLatexFileDirectories(), newMetaData.getLatexFileDirectories());
+ addToListIfDiff(changes, DifferenceType.DEFAULT_KEY_PATTERN, originalMetaData.getDefaultCiteKeyPattern(), newMetaData.getDefaultCiteKeyPattern());
+ addToListIfDiff(changes, DifferenceType.SAVE_ACTIONS, originalMetaData.getSaveActions(), newMetaData.getSaveActions());
+ addToListIfDiff(changes, DifferenceType.MODE, originalMetaData.getMode(), newMetaData.getMode());
+ addToListIfDiff(changes, DifferenceType.GENERAL_FILE_DIRECTORY, originalMetaData.getDefaultFileDirectory(), newMetaData.getDefaultFileDirectory());
+ addToListIfDiff(changes, DifferenceType.CONTENT_SELECTOR, originalMetaData.getContentSelectors(), newMetaData.getContentSelectors());
return changes;
}
diff --git a/src/main/java/org/jabref/logic/crawler/StudyRepository.java b/src/main/java/org/jabref/logic/crawler/StudyRepository.java
index 0911fa3d943a..9e3abbe08049 100644
--- a/src/main/java/org/jabref/logic/crawler/StudyRepository.java
+++ b/src/main/java/org/jabref/logic/crawler/StudyRepository.java
@@ -28,6 +28,7 @@
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
import org.jabref.model.study.FetchResult;
import org.jabref.model.study.QueryResult;
import org.jabref.model.study.Study;
@@ -427,7 +428,7 @@ private void generateCiteKeys(BibDatabaseContext existingEntries, BibDatabase ta
private void writeResultToFile(Path pathToFile, BibDatabaseContext context) throws SaveException {
try (AtomicFileWriter fileWriter = new AtomicFileWriter(pathToFile, StandardCharsets.UTF_8)) {
SaveConfiguration saveConfiguration = new SaveConfiguration()
- .withSaveOrder(context.getMetaData().getSaveOrder().orElse(SaveOrder.getDefaultSaveOrder()))
+ .withSaveOrder(context.getMetaData().getSaveOrder().map(so -> SelfContainedSaveOrder.of(so)).orElse(SaveOrder.getDefaultSaveOrder()))
.withReformatOnSave(preferencesService.getLibraryPreferences().shouldAlwaysReformatOnSave());
BibWriter bibWriter = new BibWriter(fileWriter, OS.NEWLINE);
BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter(
diff --git a/src/main/java/org/jabref/logic/exporter/BibDatabaseWriter.java b/src/main/java/org/jabref/logic/exporter/BibDatabaseWriter.java
index 80be19dcc575..e8c417b157da 100644
--- a/src/main/java/org/jabref/logic/exporter/BibDatabaseWriter.java
+++ b/src/main/java/org/jabref/logic/exporter/BibDatabaseWriter.java
@@ -39,6 +39,7 @@
import org.jabref.model.entry.field.InternalField;
import org.jabref.model.metadata.MetaData;
import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
import org.jabref.model.strings.StringUtil;
import org.jooq.lambda.Unchecked;
@@ -70,6 +71,7 @@ public BibDatabaseWriter(BibWriter bibWriter,
this.saveConfiguration = saveConfiguration;
this.keyPatternPreferences = keyPatternPreferences;
this.entryTypesManager = entryTypesManager;
+ assert saveConfiguration.getSaveOrder().getOrderType() != SaveOrder.OrderType.TABLE;
}
private static List applySaveActions(List toChange, MetaData metaData) {
@@ -128,7 +130,7 @@ private static List> getSaveComparators(SaveOrder saveOrder
* 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(List entriesToSort, SaveOrder saveOrder) {
+ public static List getSortedEntries(List entriesToSort, SelfContainedSaveOrder saveOrder) {
Objects.requireNonNull(entriesToSort);
Objects.requireNonNull(saveOrder);
diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java
index 59603deaa2a1..78373ef98d49 100644
--- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java
+++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java
@@ -13,7 +13,7 @@
import org.jabref.logic.xmp.XmpPreferences;
import org.jabref.model.database.BibDatabaseMode;
import org.jabref.model.entry.BibEntryTypesManager;
-import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
import org.jabref.preferences.PreferencesService;
public class ExporterFactory {
@@ -29,7 +29,7 @@ public static ExporterFactory create(PreferencesService preferencesService,
List customFormats = preferencesService.getExportPreferences().getCustomExporters();
LayoutFormatterPreferences layoutPreferences = preferencesService.getLayoutFormatterPreferences();
- SaveOrder saveOrder = preferencesService.getExportConfiguration().getSaveOrder();
+ SelfContainedSaveOrder saveOrder = SelfContainedSaveOrder.of(preferencesService.getExportConfiguration().getSaveOrder());
XmpPreferences xmpPreferences = preferencesService.getXmpPreferences();
FieldPreferences fieldPreferences = preferencesService.getFieldPreferences();
BibDatabaseMode bibDatabaseMode = preferencesService.getLibraryPreferences().getDefaultBibDatabaseMode();
diff --git a/src/main/java/org/jabref/logic/exporter/SaveConfiguration.java b/src/main/java/org/jabref/logic/exporter/SaveConfiguration.java
index 9a93467390f8..29742fd4a586 100644
--- a/src/main/java/org/jabref/logic/exporter/SaveConfiguration.java
+++ b/src/main/java/org/jabref/logic/exporter/SaveConfiguration.java
@@ -1,6 +1,8 @@
package org.jabref.logic.exporter;
+import org.jabref.gui.autosaveandbackup.BackupManager;
import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
public class SaveConfiguration {
@@ -8,11 +10,11 @@ public class SaveConfiguration {
public static final String ENCODING_PREFIX = "Encoding: ";
private boolean reformatFile;
- private SaveOrder saveOrder;
+ private SelfContainedSaveOrder saveOrder;
private boolean makeBackup;
private BibDatabaseWriter.SaveType saveType;
- public SaveConfiguration(SaveOrder saveOrder,
+ public SaveConfiguration(SelfContainedSaveOrder saveOrder,
Boolean makeBackup,
BibDatabaseWriter.SaveType saveType,
Boolean reformatFile) {
@@ -29,11 +31,11 @@ public SaveConfiguration() {
false);
}
- public SaveOrder getSaveOrder() {
+ public SelfContainedSaveOrder getSaveOrder() {
return saveOrder;
}
- public SaveConfiguration withSaveOrder(SaveOrder newSaveOrder) {
+ public SaveConfiguration withSaveOrder(SelfContainedSaveOrder newSaveOrder) {
this.saveOrder = newSaveOrder;
return this;
}
@@ -43,7 +45,7 @@ public boolean shouldMakeBackup() {
}
/**
- * Required by {@link org.jabref.logic.autosaveandbackup.BackupManager}. Should not be used in other settings
+ * Required by {@link BackupManager}. Should not be used in other settings
*
* @param newMakeBackup whether a backup (.bak file) should be made
*/
diff --git a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java
index 178171837040..c2e0e7e6e1c3 100644
--- a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java
+++ b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java
@@ -29,6 +29,7 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.types.EntryType;
import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,7 +51,7 @@ public class TemplateExporter extends Exporter {
private final String lfFileName;
private final String directory;
private final LayoutFormatterPreferences layoutPreferences;
- private final SaveOrder saveOrder;
+ private final SelfContainedSaveOrder saveOrder;
private boolean customExport;
private BlankLineBehaviour blankLineBehaviour;
@@ -82,7 +83,7 @@ public TemplateExporter(String name,
String lfFileName,
String extension,
LayoutFormatterPreferences layoutPreferences,
- SaveOrder saveOrder) {
+ SelfContainedSaveOrder saveOrder) {
this(name,
name,
lfFileName,
@@ -107,7 +108,7 @@ public TemplateExporter(String displayName,
String directory,
FileType extension,
LayoutFormatterPreferences layoutPreferences,
- SaveOrder saveOrder) {
+ SelfContainedSaveOrder saveOrder) {
this(displayName, consoleName, lfFileName, directory, extension, layoutPreferences, saveOrder, null);
}
@@ -128,7 +129,7 @@ public TemplateExporter(String displayName,
String directory,
FileType extension,
LayoutFormatterPreferences layoutPreferences,
- SaveOrder saveOrder,
+ SelfContainedSaveOrder saveOrder,
BlankLineBehaviour blankLineBehaviour) {
super(consoleName, displayName, extension);
if (Objects.requireNonNull(lfFileName).endsWith(LAYOUT_EXTENSION)) {
diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java
index b3680b57b9b3..278b05d95951 100644
--- a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java
+++ b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java
@@ -230,7 +230,7 @@ private static Optional getRawCitationMarkerField(BibEntry entr
Objects.requireNonNull(entry, "Entry cannot be null");
Objects.requireNonNull(database, "database cannot be null");
- for (Field field : fields /* FieldFactory.parseOrFields(fields)*/) {
+ for (Field field : fields.getFields() /* FieldFactory.parseOrFields(fields)*/) {
Optional optionalContent = entry.getResolvedFieldOrAlias(field, database);
final boolean foundSomething = optionalContent.isPresent()
&& !optionalContent.get().trim().isEmpty();
diff --git a/src/main/java/org/jabref/logic/util/io/BackupFileUtil.java b/src/main/java/org/jabref/logic/util/io/BackupFileUtil.java
index 0e499b5c51e8..bea88213b6f6 100644
--- a/src/main/java/org/jabref/logic/util/io/BackupFileUtil.java
+++ b/src/main/java/org/jabref/logic/util/io/BackupFileUtil.java
@@ -9,6 +9,7 @@
import java.util.HexFormat;
import java.util.Optional;
+import org.jabref.gui.autosaveandbackup.BackupManager;
import org.jabref.logic.util.BackupFileType;
import org.slf4j.Logger;
@@ -33,7 +34,7 @@ private BackupFileUtil() {
* In case that fails, the return path of the .bak file is set to be next to the .bib file
*
*
- * Note that this backup is different from the .sav
file generated by {@link org.jabref.logic.autosaveandbackup.BackupManager}
+ * Note that this backup is different from the .sav
file generated by {@link BackupManager}
* (and configured in the preferences as "make backups")
*
*/
diff --git a/src/main/java/org/jabref/model/database/event/AutosaveEvent.java b/src/main/java/org/jabref/model/database/event/AutosaveEvent.java
index b89ffe7d8c46..dbfd66d98580 100644
--- a/src/main/java/org/jabref/model/database/event/AutosaveEvent.java
+++ b/src/main/java/org/jabref/model/database/event/AutosaveEvent.java
@@ -1,7 +1,9 @@
package org.jabref.model.database.event;
+import org.jabref.gui.autosaveandbackup.AutosaveManager;
+
/**
- * This Event is fired from {@link org.jabref.logic.autosaveandbackup.AutosaveManager} in case that a save task is pending.
+ * This Event is fired from {@link AutosaveManager} in case that a save task is pending.
*/
public class AutosaveEvent {
// no data
diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java
index 3f6b82ae6b4a..7fdd429a5976 100644
--- a/src/main/java/org/jabref/model/entry/BibEntry.java
+++ b/src/main/java/org/jabref/model/entry/BibEntry.java
@@ -158,7 +158,7 @@ public Optional setMonth(Month parsedMonth) {
}
public Optional getResolvedFieldOrAlias(OrFields fields, BibDatabase database) {
- for (Field field : fields) {
+ for (Field field : fields.getFields()) {
Optional value = getResolvedFieldOrAlias(field, database);
if (value.isPresent()) {
return value;
diff --git a/src/main/java/org/jabref/model/entry/BibEntryTypeBuilder.java b/src/main/java/org/jabref/model/entry/BibEntryTypeBuilder.java
index ddc510d7d4bc..b8613157ac6e 100644
--- a/src/main/java/org/jabref/model/entry/BibEntryTypeBuilder.java
+++ b/src/main/java/org/jabref/model/entry/BibEntryTypeBuilder.java
@@ -75,8 +75,9 @@ public BibEntryTypeBuilder withRequiredFields(List first, Field... req
public BibEntryType build() {
// Treat required fields as important ones
Stream requiredAsImportant = requiredFields.stream()
- .flatMap(Set::stream)
- .map(field -> new BibField(field, FieldPriority.IMPORTANT));
+ .map(OrFields::getFields)
+ .flatMap(Set::stream)
+ .map(field -> new BibField(field, FieldPriority.IMPORTANT));
Set allFields = Stream.concat(fields.stream(), requiredAsImportant).collect(Collectors.toCollection(LinkedHashSet::new));
return new BibEntryType(type, allFields, requiredFields);
}
diff --git a/src/main/java/org/jabref/model/entry/field/FieldFactory.java b/src/main/java/org/jabref/model/entry/field/FieldFactory.java
index cac6bb3b2c77..645a1295221c 100644
--- a/src/main/java/org/jabref/model/entry/field/FieldFactory.java
+++ b/src/main/java/org/jabref/model/entry/field/FieldFactory.java
@@ -31,7 +31,7 @@ public static String serializeOrFields(Field... fields) {
}
public static String serializeOrFields(OrFields fields) {
- return fields.stream()
+ return fields.getFields().stream()
.map(field -> {
if (field instanceof UnknownField unknownField) {
// In case a user has put a user-defined field, the casing of that field is kept
diff --git a/src/main/java/org/jabref/model/entry/field/OrFields.java b/src/main/java/org/jabref/model/entry/field/OrFields.java
index baf848d43920..e0d24537be52 100644
--- a/src/main/java/org/jabref/model/entry/field/OrFields.java
+++ b/src/main/java/org/jabref/model/entry/field/OrFields.java
@@ -3,36 +3,80 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Set;
import java.util.StringJoiner;
-public class OrFields extends LinkedHashSet implements Comparable {
+public class OrFields implements Comparable {
+
+ private LinkedHashSet fields = new LinkedHashSet<>();
public OrFields(Field field) {
- add(field);
+ fields.add(field);
}
- public OrFields(Field... fields) {
- addAll(Arrays.asList(fields));
+ public OrFields(Field... fieldsToAdd) {
+ Arrays.stream(fieldsToAdd).forEach(fields::add);
}
- public OrFields(Collection fields) {
- addAll(fields);
+ public OrFields(Collection fieldsToAdd) {
+ fields.addAll(fieldsToAdd);
}
public String getDisplayName() {
StringJoiner joiner = new StringJoiner("/");
- for (Field field : this) {
+ for (Field field : fields) {
joiner.add(field.getDisplayName());
}
return joiner.toString();
}
public Field getPrimary() {
- return this.iterator().next();
+ return fields.iterator().next();
+ }
+
+ public Set getFields() {
+ return this.fields;
+ }
+
+ public boolean contains(Field field) {
+ return fields.contains(field);
}
@Override
public int compareTo(OrFields o) {
return FieldFactory.serializeOrFields(this).compareTo(FieldFactory.serializeOrFields(o));
}
+
+ public boolean hasExactlyOne() {
+ return this.fields.size() == 1;
+ }
+
+ public boolean isEmpty() {
+ return this.fields.isEmpty();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ OrFields orFields = (OrFields) o;
+ return Objects.equals(fields, orFields.fields);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(fields);
+ }
+
+ @Override
+ public String toString() {
+ return "OrFields{" +
+ "fields=" + fields +
+ '}';
+ }
}
diff --git a/src/main/java/org/jabref/model/metadata/ContentSelectors.java b/src/main/java/org/jabref/model/metadata/ContentSelectors.java
index d8c70e565ee9..93c85250ae91 100644
--- a/src/main/java/org/jabref/model/metadata/ContentSelectors.java
+++ b/src/main/java/org/jabref/model/metadata/ContentSelectors.java
@@ -86,4 +86,12 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(contentSelectors);
}
+
+ @Override
+ public String toString() {
+ return "ContentSelectors{" +
+ "contentSelectors=" + contentSelectors +
+ ", fieldsWithSelectors=" + getFieldsWithSelectors() +
+ '}';
+ }
}
diff --git a/src/main/java/org/jabref/model/metadata/SaveOrder.java b/src/main/java/org/jabref/model/metadata/SaveOrder.java
index 2161d7526c5a..8186a2514c30 100644
--- a/src/main/java/org/jabref/model/metadata/SaveOrder.java
+++ b/src/main/java/org/jabref/model/metadata/SaveOrder.java
@@ -11,9 +11,15 @@
import org.slf4j.LoggerFactory;
/**
- * Stores the save order config from MetaData
+ * Stores the save order config for a library
*
- * Format: <choice>, a pair of field + ascending (boolean)
+ * Format: <choice> ({@link OrderType}, a pair of {@link Field} + descending (boolean)
+ *
+ *
+ * Note that {@link OrderType#TABLE} can only be used as "intermediate" setting. When passing SaveOrder
+ * to {@link org.jabref.logic.exporter.BibDatabaseWriter}, the orderType must be different. Reason: The writer
+ * does not have access to the UI.
+ *
*/
public class SaveOrder {
@@ -61,8 +67,8 @@ public static SaveOrder parse(List orderedData) {
return new SaveOrder(orderedData);
}
- public static SaveOrder getDefaultSaveOrder() {
- return new SaveOrder(OrderType.ORIGINAL, List.of());
+ public static SelfContainedSaveOrder getDefaultSaveOrder() {
+ return new SelfContainedSaveOrder(OrderType.ORIGINAL, List.of());
}
public OrderType getOrderType() {
@@ -102,11 +108,7 @@ public String toString() {
*/
public List getAsStringList() {
List res = new ArrayList<>(7);
- if (orderType == OrderType.ORIGINAL) {
- res.add(OrderType.ORIGINAL.toString());
- } else {
- res.add(OrderType.SPECIFIED.toString());
- }
+ res.add(orderType.toString());
for (SortCriterion sortCriterion : sortCriteria) {
res.add(sortCriterion.field.getName());
diff --git a/src/main/java/org/jabref/model/metadata/SelfContainedSaveOrder.java b/src/main/java/org/jabref/model/metadata/SelfContainedSaveOrder.java
new file mode 100644
index 000000000000..1c40945e9edc
--- /dev/null
+++ b/src/main/java/org/jabref/model/metadata/SelfContainedSaveOrder.java
@@ -0,0 +1,27 @@
+package org.jabref.model.metadata;
+
+import java.util.List;
+
+/**
+ * With this class, the user of an instance can directly sort things. Without looking up anything in the preferences or in the UI.
+ */
+public class SelfContainedSaveOrder extends SaveOrder {
+ public SelfContainedSaveOrder(OrderType orderType, List sortCriteria) {
+ super(orderType, sortCriteria);
+ if (orderType == OrderType.TABLE) {
+ throw new IllegalArgumentException("TABLE requires external lookup.");
+ }
+ }
+
+ /**
+ * Converts a SaveOrder to a SelfContainedSaveOrder
+ *
+ * @throws IllegalArgumentException if {@code saveOrder} has {@link OrderType#TABLE}
+ */
+ public static SelfContainedSaveOrder of(SaveOrder saveOrder) {
+ if (saveOrder instanceof SelfContainedSaveOrder order) {
+ return order;
+ }
+ return new SelfContainedSaveOrder(saveOrder.getOrderType(), saveOrder.getSortCriteria());
+ }
+}
diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java
index e48e39553c1a..651ecc4ca858 100644
--- a/src/main/java/org/jabref/preferences/JabRefPreferences.java
+++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java
@@ -111,6 +111,7 @@
import org.jabref.model.entry.types.EntryTypeFactory;
import org.jabref.model.groups.GroupHierarchyType;
import org.jabref.model.metadata.SaveOrder;
+import org.jabref.model.metadata.SelfContainedSaveOrder;
import org.jabref.model.search.rules.SearchRules;
import org.jabref.model.strings.StringUtil;
@@ -2255,18 +2256,11 @@ private void storeExportSaveOrder(SaveOrder saveOrder) {
putBoolean(EXPORT_TERTIARY_SORT_DESCENDING, saveOrder.getSortCriteria().get(2).descending);
}
- private SaveOrder getTableSaveOrder() {
+ public SaveOrder getTableSaveOrder() {
List sortOrder = mainTableColumnPreferences.getColumnSortOrder();
- List criteria = new ArrayList<>();
-
- for (var column : sortOrder) {
- boolean descending = column.getSortType() == SortType.DESCENDING;
- criteria.add(new SaveOrder.SortCriterion(
- FieldFactory.parseField(column.getQualifier()),
- descending));
- }
-
- return new SaveOrder(SaveOrder.OrderType.TABLE, criteria);
+ return new SaveOrder(
+ SaveOrder.OrderType.TABLE,
+ sortOrder.stream().flatMap(model -> model.getSortCriteria().stream()).toList());
}
@Override
@@ -2278,7 +2272,7 @@ public SaveConfiguration getExportConfiguration() {
};
return new SaveConfiguration()
- .withSaveOrder(saveOrder)
+ .withSaveOrder(SelfContainedSaveOrder.of(saveOrder))
.withReformatOnSave(getLibraryPreferences().shouldAlwaysReformatOnSave());
}
diff --git a/src/main/java/org/jabref/preferences/PreferencesService.java b/src/main/java/org/jabref/preferences/PreferencesService.java
index 0150a4314d27..485e93ded568 100644
--- a/src/main/java/org/jabref/preferences/PreferencesService.java
+++ b/src/main/java/org/jabref/preferences/PreferencesService.java
@@ -70,6 +70,9 @@ public interface PreferencesService {
ImportFormatPreferences getImportFormatPreferences();
+ /**
+ * Returns the export configuration. The contained SaveConfiguration is a {@link org.jabref.model.metadata.SelfContainedSaveOrder}
+ */
SaveConfiguration getExportConfiguration();
BibEntryTypesManager getCustomEntryTypesRepository();
diff --git a/src/main/resources/tinylog.properties b/src/main/resources/tinylog.properties
index b4340fa32e9a..9eecb7934bd9 100644
--- a/src/main/resources/tinylog.properties
+++ b/src/main/resources/tinylog.properties
@@ -7,3 +7,4 @@ writerAzure = application insights
exception = strip: jdk.internal
#level@org.jabref.model.entry.BibEntry = debug
+level@org.jabref.gui.maintable.PersistenceVisualStateTable = debug
diff --git a/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerDiscardedTest.java b/src/test/java/org/jabref/gui/autosaveandbackup/BackupManagerDiscardedTest.java
similarity index 95%
rename from src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerDiscardedTest.java
rename to src/test/java/org/jabref/gui/autosaveandbackup/BackupManagerDiscardedTest.java
index ee60abcc067c..e7d868ee8622 100644
--- a/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerDiscardedTest.java
+++ b/src/test/java/org/jabref/gui/autosaveandbackup/BackupManagerDiscardedTest.java
@@ -1,4 +1,4 @@
-package org.jabref.logic.autosaveandbackup;
+package org.jabref.gui.autosaveandbackup;
import java.io.IOException;
import java.io.Writer;
@@ -6,6 +6,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
+import org.jabref.gui.LibraryTab;
import org.jabref.logic.exporter.AtomicFileWriter;
import org.jabref.logic.exporter.BibWriter;
import org.jabref.logic.exporter.BibtexDatabaseWriter;
@@ -63,7 +64,7 @@ public void setup(@TempDir Path tempDir) throws Exception {
saveDatabase();
- backupManager = new BackupManager(bibDatabaseContext, bibEntryTypesManager, preferencesService);
+ backupManager = new BackupManager(mock(LibraryTab.class), bibDatabaseContext, bibEntryTypesManager, preferencesService);
makeBackup();
}
diff --git a/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerTest.java b/src/test/java/org/jabref/gui/autosaveandbackup/BackupManagerTest.java
similarity index 93%
rename from src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerTest.java
rename to src/test/java/org/jabref/gui/autosaveandbackup/BackupManagerTest.java
index 3573bd7aa8bf..c1a0caf267d0 100644
--- a/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerTest.java
+++ b/src/test/java/org/jabref/gui/autosaveandbackup/BackupManagerTest.java
@@ -1,4 +1,4 @@
-package org.jabref.logic.autosaveandbackup;
+package org.jabref.gui.autosaveandbackup;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -8,6 +8,7 @@
import java.util.List;
import java.util.Optional;
+import org.jabref.gui.LibraryTab;
import org.jabref.logic.util.BackupFileType;
import org.jabref.logic.util.OS;
import org.jabref.logic.util.io.BackupFileUtil;
@@ -141,7 +142,11 @@ public void shouldNotCreateABackup(@TempDir Path customDir) throws Exception {
when(preferences.getFilePreferences()).thenReturn(filePreferences);
when(filePreferences.getBackupDirectory()).thenReturn(backupDir);
- BackupManager manager = BackupManager.start(database, mock(BibEntryTypesManager.class, Answers.RETURNS_DEEP_STUBS), preferences);
+ BackupManager manager = BackupManager.start(
+ mock(LibraryTab.class),
+ database,
+ mock(BibEntryTypesManager.class, Answers.RETURNS_DEEP_STUBS),
+ preferences);
manager.listen(new MetaDataChangedEvent(new MetaData()));
BackupManager.shutdown(database, backupDir, false);
@@ -164,7 +169,11 @@ public void shouldCreateABackup(@TempDir Path customDir) throws Exception {
when(filePreferences.getBackupDirectory()).thenReturn(backupDir);
when(filePreferences.shouldCreateBackup()).thenReturn(true);
- BackupManager manager = BackupManager.start(database, mock(BibEntryTypesManager.class, Answers.RETURNS_DEEP_STUBS), preferences);
+ BackupManager manager = BackupManager.start(
+ mock(LibraryTab.class),
+ database,
+ mock(BibEntryTypesManager.class, Answers.RETURNS_DEEP_STUBS),
+ preferences);
manager.listen(new MetaDataChangedEvent(new MetaData()));
Optional fullBackupPath = manager.determineBackupPathForNewBackup(backupDir);
diff --git a/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java b/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java
index 5321fe1ae7ca..9602c84fd59f 100644
--- a/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java
+++ b/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java
@@ -23,6 +23,7 @@
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.types.StandardEntryType;
import org.jabref.model.metadata.MetaData;
+import org.jabref.model.metadata.SaveOrder;
import org.jabref.preferences.FilePreferences;
import org.jabref.preferences.LibraryPreferences;
import org.jabref.preferences.PreferencesService;
@@ -92,6 +93,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List
when(preferences.getFilePreferences()).thenReturn(filePreferences);
when(preferences.getLibraryPreferences()).thenReturn(libraryPreferences);
when(preferences.getExportPreferences().getLastExportExtension()).thenReturn("HTML");
+ when(preferences.getExportConfiguration().getSaveOrder()).thenReturn(SaveOrder.getDefaultSaveOrder());
when(stateManager.getSelectedEntries()).thenReturn(selectedEntries);
when(stateManager.getActiveDatabase()).thenReturn(Optional.ofNullable(databaseContext));
// noinspection ConstantConditions since databaseContext is mocked
diff --git a/src/test/java/org/jabref/logic/bibtex/comparator/FieldComparatorTest.java b/src/test/java/org/jabref/logic/bibtex/comparator/FieldComparatorTest.java
index 59c9d1161329..47ed17128ed0 100644
--- a/src/test/java/org/jabref/logic/bibtex/comparator/FieldComparatorTest.java
+++ b/src/test/java/org/jabref/logic/bibtex/comparator/FieldComparatorTest.java
@@ -202,25 +202,52 @@ public void compareParsableWithNonParsableNumericFieldDescending() throws Except
}
@ParameterizedTest
- @MethodSource("provideArgumentsForNumericalComparison")
- public void compareNumericalValues(int comparisonResult, String id1, String id2, String errorMessage) {
+ @MethodSource
+ public void compareNumericalValues(int comparisonResult, String id1, String id2, String message) {
FieldComparator comparator = new FieldComparator(StandardField.PMID);
BibEntry entry1 = new BibEntry()
.withField(StandardField.PMID, id1);
BibEntry entry2 = new BibEntry()
.withField(StandardField.PMID, id2);
- assertEquals(comparisonResult, comparator.compare(entry1, entry2), errorMessage);
+ assertEquals(comparisonResult, comparator.compare(entry1, entry2), message);
}
- private static Stream provideArgumentsForNumericalComparison() {
+ private static Stream compareNumericalValues() {
return Stream.of(
- Arguments.of(0, "123456", "123456", "IDs are lexicographically not equal [1]"),
- Arguments.of(1, "234567", "123456", "234567 is lexicographically smaller than 123456"),
- Arguments.of(1, "abc##z", "123456", "abc##z is lexicographically smaller than 123456 "),
- Arguments.of(0, "", "", "IDs are lexicographically not equal [2]"),
- Arguments.of(1, "", "123456", "No ID is lexicographically smaller than 123456"),
- Arguments.of(-1, "123456", "", "123456 is lexicographically greater than no ID")
+ Arguments.of(0, "123456", "123456", "IDs should be lexicographically equal"),
+ Arguments.of(1, "234567", "123456", "234567 should be lexicographically greater than 123456"),
+ Arguments.of(1, "abc##z", "123456", "abc##z should be lexicographically greater than 123456 "),
+ Arguments.of(0, "", "", "Empty IDs should be lexicographically equal"),
+ Arguments.of(-1, "", "123456", "No ID should be lexicographically smaller than 123456"),
+ Arguments.of(1, "123456", "", "123456 should be lexicographically greater than no ID")
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ public void nullTests(int comparisonResult, String firstValue, String secondValue) {
+ FieldComparator comparator = new FieldComparator(StandardField.TITLE);
+
+ BibEntry entry1 = new BibEntry();
+ if (firstValue != null) {
+ entry1.setField(StandardField.TITLE, firstValue);
+ }
+
+ BibEntry entry2 = new BibEntry();
+ if (secondValue != null) {
+ entry2.setField(StandardField.TITLE, secondValue);
+ }
+
+ assertEquals(comparisonResult, comparator.compare(entry1, entry2));
+ }
+
+ private static Stream nullTests() {
+ return Stream.of(
+ Arguments.of(0, null, null),
+ Arguments.of(0, "value", "value"),
+ Arguments.of(-1, null, "value"),
+ Arguments.of(1, "value", null)
);
}
}
diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib b/src/test/resources/org/jabref/gui/autosaveandbackup/changes.bib
similarity index 100%
rename from src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib
rename to src/test/resources/org/jabref/gui/autosaveandbackup/changes.bib
diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib.bak b/src/test/resources/org/jabref/gui/autosaveandbackup/changes.bib.bak
similarity index 100%
rename from src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib.bak
rename to src/test/resources/org/jabref/gui/autosaveandbackup/changes.bib.bak
diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/no-autosave.bib b/src/test/resources/org/jabref/gui/autosaveandbackup/no-autosave.bib
similarity index 100%
rename from src/test/resources/org/jabref/logic/autosaveandbackup/no-autosave.bib
rename to src/test/resources/org/jabref/gui/autosaveandbackup/no-autosave.bib
diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib b/src/test/resources/org/jabref/gui/autosaveandbackup/no-changes.bib
similarity index 100%
rename from src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib
rename to src/test/resources/org/jabref/gui/autosaveandbackup/no-changes.bib
diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib.bak b/src/test/resources/org/jabref/gui/autosaveandbackup/no-changes.bib.bak
similarity index 100%
rename from src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib.bak
rename to src/test/resources/org/jabref/gui/autosaveandbackup/no-changes.bib.bak
From 6030e7d3db9ef80c25516147584246bad6b0f905 Mon Sep 17 00:00:00 2001
From: Christoph
Date: Sat, 2 Sep 2023 21:54:19 +0200
Subject: [PATCH 3/4] Update bug_report.yml
Add 5.10
---
.github/ISSUE_TEMPLATE/bug_report.yml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 783e39dd0577..5f136688ca4e 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -12,8 +12,7 @@ body:
attributes:
label: JabRef version
options:
- - "5.9 (latest release)"
- - "3.8.2"
+ - "5.10 (latest release)"
- Latest development branch build (please note build date below)
- Other (please describe below)
description: The version as shown in the about dialog.
@@ -42,7 +41,7 @@ body:
- type: checkboxes
attributes:
- label: Checked with the latest development build
+ label: Checked with the latest development build (copy version output from About dialog)
description: |
Please always test if the bug is still reproducible in the latest development version. We are constantly improving JabRef and some bugs may already be fixed. If you already use a development version, ensure that you use the latest one.
You can download the latest development build at: https://builds.jabref.org/main/ . **Please make a backup of your library before you try out this version.**
From 57f97f23ac939476864791a2db58939d1a2fb819 Mon Sep 17 00:00:00 2001
From: Christoph
Date: Sat, 2 Sep 2023 23:40:36 +0200
Subject: [PATCH 4/4] Add method for detecting journal abbrev delimiter
(#10281)
---
.../logic/journals/AbbreviationFormat.java | 10 +++-
.../logic/journals/AbbreviationParser.java | 57 ++++++++-----------
.../logic/journals/AbbreviationWriter.java | 2 +-
.../journals/JournalAbbreviationLoader.java | 2 +-
.../JournalAbbreviationRepository.java | 36 ++++++------
.../JournalAbbreviationsViewModelTabTest.java | 4 +-
.../journals/AbbreviationParserTest.java | 47 +++++++++++++++
.../journals/AbbreviationWriterTest.java | 4 +-
8 files changed, 103 insertions(+), 59 deletions(-)
create mode 100644 src/test/java/org/jabref/logic/journals/AbbreviationParserTest.java
diff --git a/src/main/java/org/jabref/logic/journals/AbbreviationFormat.java b/src/main/java/org/jabref/logic/journals/AbbreviationFormat.java
index 0388b048e94b..21734cad692f 100644
--- a/src/main/java/org/jabref/logic/journals/AbbreviationFormat.java
+++ b/src/main/java/org/jabref/logic/journals/AbbreviationFormat.java
@@ -4,20 +4,24 @@
public final class AbbreviationFormat {
- public static final char DELIMITER = ';';
+ public static final char DELIMITER = ',';
public static final char ESCAPE = '\\';
public static final char QUOTE = '"';
private AbbreviationFormat() {
}
- public static CSVFormat getCSVFormat() {
+ public static CSVFormat getCSVFormatWithDelimiter(char delimiter) {
return CSVFormat.DEFAULT.builder()
.setIgnoreEmptyLines(true)
- .setDelimiter(DELIMITER)
+ .setDelimiter(delimiter)
.setEscape(ESCAPE)
.setQuote(QUOTE)
.setTrim(true)
.build();
}
+
+ public static CSVFormat getCSVFormatWithDefaultDilimeter() {
+ return getCSVFormatWithDelimiter(DELIMITER);
+ }
}
diff --git a/src/main/java/org/jabref/logic/journals/AbbreviationParser.java b/src/main/java/org/jabref/logic/journals/AbbreviationParser.java
index 9a9f67f0bfe6..5c84eb8ec17b 100644
--- a/src/main/java/org/jabref/logic/journals/AbbreviationParser.java
+++ b/src/main/java/org/jabref/logic/journals/AbbreviationParser.java
@@ -2,58 +2,37 @@
import java.io.BufferedReader;
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.Files;
import java.nio.file.Path;
+import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Reads abbreviation files (CSV format) into a list of Abbreviations.
*/
public class AbbreviationParser {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(AbbreviationParser.class);
+ private static final Character[] DELIMITERS = {';', ','};
+ private static final char NO_DELIMITER = '\0'; // empty char
// Ensures ordering while preventing duplicates
private final LinkedHashSet abbreviations = new LinkedHashSet<>();
- void readJournalListFromResource(String resourceFileName) {
- try (InputStream stream = JournalAbbreviationRepository.class.getResourceAsStream(resourceFileName);
- BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
- readJournalList(reader);
- } catch (IOException e) {
- LOGGER.error(String.format("Could not read journal list from file %s", resourceFileName), e);
- }
- }
-
- public void readJournalListFromFile(Path file) throws IOException {
- readJournalListFromFile(file, StandardCharsets.UTF_8);
- }
-
- public void readJournalListFromFile(Path file, Charset encoding) throws IOException {
- try (BufferedReader reader = Files.newBufferedReader(file, encoding)) {
- readJournalList(reader);
- }
- }
-
- /**
+ /*
* Read the given file, which should contain a list of journal names and their abbreviations. Each line should be
- * formatted as: "Full Journal Name;Abbr. Journal Name;[Shortest Unique Abbreviation]"
+ * formatted as: "Full Journal Name,Abbr. Journal Name,[Shortest Unique Abbreviation]"
+ * Tries to detect the delimiter, if comma or semicolon is used to ensure backwards compatibility
*
- * @param reader a given file into a Reader object
+ * @param file Path the given file
*/
- private void readJournalList(Reader reader) throws IOException {
- try (CSVParser csvParser = new CSVParser(reader, AbbreviationFormat.getCSVFormat())) {
+ void readJournalListFromFile(Path file) throws IOException {
+ char delimiter = detectDelimiter(file);
+
+ try (CSVParser csvParser = new CSVParser(Files.newBufferedReader(file, StandardCharsets.UTF_8), AbbreviationFormat.getCSVFormatWithDelimiter(delimiter))) {
for (CSVRecord csvRecord : csvParser) {
String name = csvRecord.size() > 0 ? csvRecord.get(0) : "";
String abbreviation = csvRecord.size() > 1 ? csvRecord.get(1) : "";
@@ -70,6 +49,20 @@ private void readJournalList(Reader reader) throws IOException {
}
}
+ private char detectDelimiter(Path file) throws IOException {
+ try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
+ String line = reader.readLine();
+
+ if (line == null) {
+ return NO_DELIMITER;
+ }
+ return Arrays.stream(DELIMITERS)
+ .filter(s -> line.contains(s.toString()))
+ .findFirst()
+ .orElse(NO_DELIMITER);
+ }
+ }
+
public Collection getAbbreviations() {
return abbreviations;
}
diff --git a/src/main/java/org/jabref/logic/journals/AbbreviationWriter.java b/src/main/java/org/jabref/logic/journals/AbbreviationWriter.java
index 4a3054f7634a..e60954c521b5 100644
--- a/src/main/java/org/jabref/logic/journals/AbbreviationWriter.java
+++ b/src/main/java/org/jabref/logic/journals/AbbreviationWriter.java
@@ -26,7 +26,7 @@ private AbbreviationWriter() {
*/
public static void writeOrCreate(Path path, List abbreviations) throws IOException {
try (OutputStreamWriter writer = new OutputStreamWriter(Files.newOutputStream(path), StandardCharsets.UTF_8);
- CSVPrinter csvPrinter = new CSVPrinter(writer, AbbreviationFormat.getCSVFormat())) {
+ CSVPrinter csvPrinter = new CSVPrinter(writer, AbbreviationFormat.getCSVFormatWithDefaultDilimeter())) {
for (Abbreviation entry : abbreviations) {
if (entry.isDefaultShortestUniqueAbbreviation()) {
csvPrinter.printRecord(entry.getName(), entry.getAbbreviation());
diff --git a/src/main/java/org/jabref/logic/journals/JournalAbbreviationLoader.java b/src/main/java/org/jabref/logic/journals/JournalAbbreviationLoader.java
index 1c0717a943c7..2607293ac108 100644
--- a/src/main/java/org/jabref/logic/journals/JournalAbbreviationLoader.java
+++ b/src/main/java/org/jabref/logic/journals/JournalAbbreviationLoader.java
@@ -46,7 +46,7 @@ public static JournalAbbreviationRepository loadRepository(JournalAbbreviationPr
// Read external lists
List lists = journalAbbreviationPreferences.getExternalJournalLists();
- if (!(lists.isEmpty())) {
+ if (lists != null && !(lists.isEmpty())) {
// reversing ensures that the latest lists overwrites the former one
Collections.reverse(lists);
for (String filename : lists) {
diff --git a/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java b/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java
index ca0db044368b..10f9778f825b 100644
--- a/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java
+++ b/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java
@@ -27,22 +27,23 @@ public class JournalAbbreviationRepository {
private final TreeSet customAbbreviations = new TreeSet<>();
public JournalAbbreviationRepository(Path journalList) {
- MVStore store = new MVStore.Builder().readOnly().fileName(journalList.toAbsolutePath().toString()).open();
- MVMap mvFullToAbbreviationObject = store.openMap("FullToAbbreviation");
-
- mvFullToAbbreviationObject.forEach((name, abbreviation) -> {
- String abbrevationString = abbreviation.getAbbreviation();
- String shortestUniqueAbbreviation = abbreviation.getShortestUniqueAbbreviation();
- Abbreviation newAbbreviation = new Abbreviation(
- name,
- abbrevationString,
- shortestUniqueAbbreviation
- );
- fullToAbbreviationObject.put(name, newAbbreviation);
- abbreviationToAbbreviationObject.put(abbrevationString, newAbbreviation);
- dotlessToAbbreviationObject.put(newAbbreviation.getDotlessAbbreviation(), newAbbreviation);
- shortestUniqueToAbbreviationObject.put(shortestUniqueAbbreviation, newAbbreviation);
- });
+ MVMap mvFullToAbbreviationObject;
+ try (MVStore store = new MVStore.Builder().readOnly().fileName(journalList.toAbsolutePath().toString()).open()) {
+ mvFullToAbbreviationObject = store.openMap("FullToAbbreviation");
+ mvFullToAbbreviationObject.forEach((name, abbreviation) -> {
+ String abbrevationString = abbreviation.getAbbreviation();
+ String shortestUniqueAbbreviation = abbreviation.getShortestUniqueAbbreviation();
+ Abbreviation newAbbreviation = new Abbreviation(
+ name,
+ abbrevationString,
+ shortestUniqueAbbreviation
+ );
+ fullToAbbreviationObject.put(name, newAbbreviation);
+ abbreviationToAbbreviationObject.put(abbrevationString, newAbbreviation);
+ dotlessToAbbreviationObject.put(newAbbreviation.getDotlessAbbreviation(), newAbbreviation);
+ shortestUniqueToAbbreviationObject.put(shortestUniqueAbbreviation, newAbbreviation);
+ });
+ }
}
private static boolean isMatched(String name, Abbreviation abbreviation) {
@@ -57,10 +58,9 @@ private static boolean isMatchedAbbreviated(String name, Abbreviation abbreviati
if (isExpanded) {
return false;
}
- boolean isAbbreviated = name.equalsIgnoreCase(abbreviation.getAbbreviation())
+ return name.equalsIgnoreCase(abbreviation.getAbbreviation())
|| name.equalsIgnoreCase(abbreviation.getDotlessAbbreviation())
|| name.equalsIgnoreCase(abbreviation.getShortestUniqueAbbreviation());
- return isAbbreviated;
}
/**
diff --git a/src/test/java/org/jabref/gui/preferences/journals/JournalAbbreviationsViewModelTabTest.java b/src/test/java/org/jabref/gui/preferences/journals/JournalAbbreviationsViewModelTabTest.java
index 62cf94d2b7ae..433d736862dd 100644
--- a/src/test/java/org/jabref/gui/preferences/journals/JournalAbbreviationsViewModelTabTest.java
+++ b/src/test/java/org/jabref/gui/preferences/journals/JournalAbbreviationsViewModelTabTest.java
@@ -85,9 +85,9 @@ public TestAbbreviation(String name, String abbreviation, String shortestUniqueA
@Override
public String toString() {
if (showShortestUniqueAbbreviation) {
- return this.getName() + ";" + this.getAbbreviation() + ";" + this.getShortestUniqueAbbreviation();
+ return this.getName() + "," + this.getAbbreviation() + "," + this.getShortestUniqueAbbreviation();
}
- return this.getName() + ";" + this.getAbbreviation();
+ return this.getName() + "," + this.getAbbreviation();
}
}
diff --git a/src/test/java/org/jabref/logic/journals/AbbreviationParserTest.java b/src/test/java/org/jabref/logic/journals/AbbreviationParserTest.java
new file mode 100644
index 000000000000..3237b60588ad
--- /dev/null
+++ b/src/test/java/org/jabref/logic/journals/AbbreviationParserTest.java
@@ -0,0 +1,47 @@
+package org.jabref.logic.journals;
+
+import java.io.BufferedWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Set;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AbbreviationParserTest {
+
+ private Path csvFile;
+ private final AbbreviationParser parser = new AbbreviationParser();
+
+ private final Abbreviation abbreviation = new Abbreviation("Long Name", "L.N.", "L.N.");
+
+ @BeforeEach
+ void setup(@TempDir Path tempDir) {
+ csvFile = tempDir.resolve("test.csv");
+ }
+
+ @Test
+ void testReadingFileFromCSVWithSemicolon() throws Exception {
+ // String name, String abbreviation, String shortestUniqueAbbreviation
+ String testAbbrev = "Long Name;L.N.;L.N.";
+ try (BufferedWriter writer = Files.newBufferedWriter(csvFile, StandardCharsets.UTF_8)) {
+ writer.write(testAbbrev);
+ }
+ parser.readJournalListFromFile(csvFile);
+ assertEquals(Set.of(abbreviation), parser.getAbbreviations());
+ }
+
+ @Test
+ void testReadingFileFromCSVWithComma() throws Exception {
+ String testAbbrev = "Long Name,L.N.,L.N.";
+ try (BufferedWriter writer = Files.newBufferedWriter(csvFile, StandardCharsets.UTF_8)) {
+ writer.write(testAbbrev);
+ }
+ parser.readJournalListFromFile(csvFile);
+ assertEquals(Set.of(abbreviation), parser.getAbbreviations());
+ }
+}
diff --git a/src/test/java/org/jabref/logic/journals/AbbreviationWriterTest.java b/src/test/java/org/jabref/logic/journals/AbbreviationWriterTest.java
index c16e24b23abe..bf207b25da75 100644
--- a/src/test/java/org/jabref/logic/journals/AbbreviationWriterTest.java
+++ b/src/test/java/org/jabref/logic/journals/AbbreviationWriterTest.java
@@ -21,7 +21,7 @@ void shortestUniqueAbbreviationWrittenIfItDiffers(@TempDir Path tempDir) throws
AbbreviationWriter.writeOrCreate(
csvFile,
List.of(abbreviation));
- assertEquals(List.of("Full;Abbr;A"), Files.readAllLines(csvFile));
+ assertEquals(List.of("Full,Abbr,A"), Files.readAllLines(csvFile));
}
@Test
@@ -31,6 +31,6 @@ void doNotWriteShortestUniqueAbbreviationWrittenIfItDiffers(@TempDir Path tempDi
AbbreviationWriter.writeOrCreate(
csvFile,
List.of(abbreviation));
- assertEquals(List.of("Full;Abbr"), Files.readAllLines(csvFile));
+ assertEquals(List.of("Full,Abbr"), Files.readAllLines(csvFile));
}
}