From c1be982a0751edf57247ce7cd04de7340974477b Mon Sep 17 00:00:00 2001 From: Kevin Klein Date: Sat, 3 Sep 2022 00:20:59 +0200 Subject: [PATCH 1/8] Implement UI changes --- .../jabref/gui/slr/ManageStudyDefinition.fxml | 242 ++++++++++++------ .../gui/slr/ManageStudyDefinitionView.java | 26 +- .../slr/ManageStudyDefinitionViewModel.java | 49 +--- src/main/resources/l10n/JabRef_en.properties | 2 +- 4 files changed, 179 insertions(+), 140 deletions(-) diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinition.fxml b/src/main/java/org/jabref/gui/slr/ManageStudyDefinition.fxml index b6ea1d41f7a..297ee2c1318 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinition.fxml +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinition.fxml @@ -2,7 +2,6 @@ - @@ -19,50 +18,86 @@ - +
- + - + - + - - + + - - + + - + - - + + - + @@ -70,32 +105,48 @@ - + - + - - + + - + @@ -103,35 +154,54 @@ - + - + - + - - + + - + @@ -139,33 +209,33 @@ - + - - + - + - + @@ -196,6 +277,11 @@
- - + +
diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index ce1c5f10e3e..98e69231b23 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -13,7 +13,6 @@ import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.ButtonType; -import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -29,7 +28,6 @@ import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.ValueTableCellFactory; -import org.jabref.gui.util.ViewModelListCellFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.study.Study; import org.jabref.preferences.PreferencesService; @@ -45,7 +43,6 @@ public class ManageStudyDefinitionView extends BaseDialog @FXML private TextField addAuthor; @FXML private TextField addResearchQuestion; @FXML private TextField addQuery; - @FXML private ComboBox databaseSelector; @FXML private TextField studyDirectory; @FXML private ButtonType saveButtonType; @@ -66,7 +63,6 @@ public class ManageStudyDefinitionView extends BaseDialog @FXML private TableView databaseTable; @FXML private TableColumn databaseEnabledColumn; @FXML private TableColumn databaseColumn; - @FXML private TableColumn databaseActionColumn; @Inject private DialogService dialogService; @Inject private PreferencesService prefs; @@ -161,11 +157,8 @@ private void initQueriesTab() { } private void initDatabasesTab() { - new ViewModelListCellFactory().withText(StudyDatabaseItem::getName) - .install(databaseSelector); - databaseSelector.setItems(viewModel.getNonSelectedDatabases()); - - setupCommonPropertiesForTables(databaseSelector, this::addDatabase, databaseColumn, databaseActionColumn); + databaseColumn.setReorderable(false); + databaseColumn.setCellFactory(TextFieldTableCell.forTableColumn()); databaseEnabledColumn.setResizable(false); databaseEnabledColumn.setReorderable(false); @@ -173,13 +166,6 @@ private void initDatabasesTab() { databaseEnabledColumn.setCellFactory(CheckBoxTableCell.forTableColumn(databaseEnabledColumn)); databaseColumn.setCellValueFactory(param -> param.getValue().nameProperty()); - databaseActionColumn.setCellValueFactory(param -> param.getValue().nameProperty()); - new ValueTableCellFactory() - .withGraphic(item -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) - .withTooltip(name -> Localization.lang("Remove")) - .withOnMouseClickedEvent(item -> evt -> - viewModel.removeDatabase(item)) - .install(databaseActionColumn); databaseTable.setItems(viewModel.getDatabases()); } @@ -231,14 +217,6 @@ private void addQuery() { addQuery.setText(""); } - /** - * Add selected entry from combobox, push onto database pop from nonselecteddatabase (combobox) - */ - @FXML - private void addDatabase() { - viewModel.addDatabase(databaseSelector.getSelectionModel().getSelectedItem()); - } - @FXML public void selectStudyDirectory() { DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java index 01350ab64bb..d217b82feaf 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java @@ -2,7 +2,6 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.util.Comparator; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -37,7 +36,6 @@ public class ManageStudyDefinitionViewModel { private final ObservableList queries = FXCollections.observableArrayList(); private final ObservableList databases = FXCollections.observableArrayList(); // Hold the complement of databases for the selector - private final ObservableList nonSelectedDatabases = FXCollections.observableArrayList(); private final SimpleStringProperty directory = new SimpleStringProperty(); private Study study; @@ -54,6 +52,10 @@ public ManageStudyDefinitionViewModel(Study study, authors.addAll(study.getAuthors()); researchQuestions.addAll(study.getResearchQuestions()); queries.addAll(study.getQueries().stream().map(StudyQuery::getQuery).toList()); + + // Currently, modifying an existing study is not possible. But this code first adds all databases that are + // enabled for an existing Study object as enabled entries to the table and afterwards populates the table with + // all other available databases. databases.addAll(study.getDatabases() .stream() .map(studyDatabase -> new StudyDatabaseItem(studyDatabase.getName(), studyDatabase.isEnabled())) @@ -65,11 +67,11 @@ public ManageStudyDefinitionViewModel(Study study, } private void computeNonSelectedDatabases(ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { - nonSelectedDatabases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) - .stream() - .map(SearchBasedFetcher::getName) - .map(s -> new StudyDatabaseItem(s, true)) - .filter(studyDatabase -> !databases.contains(studyDatabase)).toList()); + databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) + .stream() + .map(SearchBasedFetcher::getName) + .map(s -> new StudyDatabaseItem(s, false)) + .filter(studyDatabase -> !databases.contains(studyDatabase)).toList()); } public StringProperty getTitle() { @@ -96,10 +98,6 @@ public ObservableList getDatabases() { return databases; } - public ObservableList getNonSelectedDatabases() { - return nonSelectedDatabases; - } - public void addAuthor(String author) { if (author.isBlank()) { return; @@ -121,16 +119,6 @@ public void addQuery(String query) { queries.add(query); } - public void addDatabase(StudyDatabaseItem database) { - if (Objects.isNull(database)) { - return; - } - nonSelectedDatabases.remove(database); - if (!databases.contains(database)) { - databases.add(database); - } - } - public SlrStudyAndDirectory saveStudy() { if (Objects.isNull(study)) { study = new Study(); @@ -139,11 +127,12 @@ public SlrStudyAndDirectory saveStudy() { study.setAuthors(authors); study.setResearchQuestions(researchQuestions); study.setQueries(queries.stream().map(StudyQuery::new).collect(Collectors.toList())); - study.setDatabases(databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).collect(Collectors.toList())); + study.setDatabases(databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).filter(StudyDatabase::isEnabled).collect(Collectors.toList())); Path studyDirectory = null; try { studyDirectory = Path.of(directory.getValueSafe()); - } catch (InvalidPathException e) { + } catch ( + InvalidPathException e) { LOGGER.error("Invalid path was provided: {}", directory); } return new SlrStudyAndDirectory(study, studyDirectory); @@ -153,20 +142,6 @@ public Property titleProperty() { return title; } - public void removeDatabase(String database) { - // If a database is added from the combo box it should be enabled by default - Optional correspondingDatabase = databases.stream().filter(studyDatabaseItem -> studyDatabaseItem.getName().equals(database)).findFirst(); - if (correspondingDatabase.isEmpty()) { - return; - } - StudyDatabaseItem databaseToRemove = correspondingDatabase.get(); - databases.remove(databaseToRemove); - databaseToRemove.setEnabled(true); - nonSelectedDatabases.add(databaseToRemove); - // Resort list - nonSelectedDatabases.sort(Comparator.comparing(StudyDatabaseItem::getName)); - } - public void setStudyDirectory(Optional studyRepositoryRoot) { getDirectory().setValue(studyRepositoryRoot.map(Path::toString).orElseGet(() -> getDirectory().getValueSafe())); } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 6dff22b68d0..d020d8e5691 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2406,7 +2406,7 @@ Database=Database Databases=Databases Manage\ study\ definition=Manage study definition Add\ Author\:=Add Author\: -Add\ Database\:=Add Database\: +Select\ Databases\:=Select the databases that should be searched\: Add\ Query\:=Add Query\: Add\ Research\ Question\:=Add Research Question\: Perform\ search\ for\ existing\ systematic\ literature\ review=Perform search for existing systematic literature review From 24996d2b415c55508a0eb04b711c30c6af46ba6f Mon Sep 17 00:00:00 2001 From: Kevin Klein Date: Sat, 3 Sep 2022 10:45:01 +0200 Subject: [PATCH 2/8] WIP Implement default selection --- .../jabref/gui/slr/ManageStudyDefinitionViewModel.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java index d217b82feaf..982df5128dd 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java @@ -2,6 +2,7 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -30,6 +31,8 @@ public class ManageStudyDefinitionViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(ManageStudyDefinitionViewModel.class); + private static final List DEFAULT_SELECTION = List.of(new StudyDatabaseItem("ACM Portal", false), new StudyDatabaseItem("IEEEXplore", false), new StudyDatabaseItem("Springer", false), new StudyDatabaseItem("DBLP", false)); + private final StringProperty title = new SimpleStringProperty(); private final ObservableList authors = FXCollections.observableArrayList(); private final ObservableList researchQuestions = FXCollections.observableArrayList(); @@ -44,6 +47,12 @@ public ManageStudyDefinitionViewModel(Study study, ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { if (Objects.isNull(study)) { + // Add databases that are selected by default first. + databases.addAll(DEFAULT_SELECTION + .stream() + .map(studyDatabase -> new StudyDatabaseItem(studyDatabase.getName(), true)) + .toList()); + computeNonSelectedDatabases(importFormatPreferences, importerPreferences); return; } From 0bedead2de843253c0307820993cb3d11aabd903 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 3 Sep 2022 12:01:34 +0200 Subject: [PATCH 3/8] Fix initialization of UI (and add test) --- .../gui/slr/ManageStudyDefinitionView.java | 19 +++++-- .../slr/ManageStudyDefinitionViewModel.java | 43 +++++++++++---- .../org/jabref/gui/slr/StudyDatabaseItem.java | 23 ++++---- .../importer/fetcher/ACMPortalFetcher.java | 4 +- .../fetcher/CompositeSearchBasedFetcher.java | 4 +- .../logic/importer/fetcher/DBLPFetcher.java | 3 +- .../jabref/logic/importer/fetcher/IEEE.java | 4 +- .../importer/fetcher/SpringerFetcher.java | 3 +- .../logic/importer/fetcher/SpringerLink.java | 3 +- .../ManageStudyDefinitionViewModelTest.java | 55 +++++++++++++++++++ 10 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index 98e69231b23..eceb736802b 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -33,12 +33,16 @@ import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.views.ViewLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This class controls the user interface of the study definition management dialog. The UI elements and their layout * are defined in the FXML file. */ public class ManageStudyDefinitionView extends BaseDialog { + private static final Logger LOGGER = LoggerFactory.getLogger(ManageStudyDefinitionView.class); + @FXML private TextField studyTitle; @FXML private TextField addAuthor; @FXML private TextField addResearchQuestion; @@ -76,7 +80,7 @@ public class ManageStudyDefinitionView extends BaseDialog /** * This can be used to either create new study objects or edit existing ones. * - * @param study null if a new study is created. Otherwise the study object to edit. + * @param study null if a new study is created. Otherwise, the study object to edit. * @param studyDirectory the directory where the study to edit is located (null if a new study is created) */ public ManageStudyDefinitionView(Study study, Path studyDirectory, Path workingDirectory) { @@ -114,11 +118,14 @@ private void setupSaveButton() { @FXML private void initialize() { - viewModel = new ManageStudyDefinitionViewModel( - study, - workingDirectory, - prefs.getImportFormatPreferences(), - prefs.getImporterPreferences()); + if (Objects.isNull(study)) { + viewModel = new ManageStudyDefinitionViewModel( + prefs.getImportFormatPreferences(), + prefs.getImporterPreferences()); + } else { + LOGGER.error("Not yet implemented"); + return; + } // Listen whether any databases are removed from selection -> Add back to the database selector studyTitle.textProperty().bindBidirectional(viewModel.titleProperty()); diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java index 982df5128dd..e07886d2ed3 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import javafx.beans.property.Property; @@ -17,6 +18,11 @@ import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.SearchBasedFetcher; import org.jabref.logic.importer.WebFetchers; +import org.jabref.logic.importer.fetcher.ACMPortalFetcher; +import org.jabref.logic.importer.fetcher.CompositeSearchBasedFetcher; +import org.jabref.logic.importer.fetcher.DBLPFetcher; +import org.jabref.logic.importer.fetcher.IEEE; +import org.jabref.logic.importer.fetcher.SpringerFetcher; import org.jabref.model.study.Study; import org.jabref.model.study.StudyDatabase; import org.jabref.model.study.StudyQuery; @@ -31,31 +37,43 @@ public class ManageStudyDefinitionViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(ManageStudyDefinitionViewModel.class); - private static final List DEFAULT_SELECTION = List.of(new StudyDatabaseItem("ACM Portal", false), new StudyDatabaseItem("IEEEXplore", false), new StudyDatabaseItem("Springer", false), new StudyDatabaseItem("DBLP", false)); + private static final Set DEFAULT_SELECTION = Set.of( + ACMPortalFetcher.FETCHER_NAME, + IEEE.FETCHER_NAME, + SpringerFetcher.FETCHER_NAME, + DBLPFetcher.FETCHER_NAME); + private final StringProperty title = new SimpleStringProperty(); private final ObservableList authors = FXCollections.observableArrayList(); private final ObservableList researchQuestions = FXCollections.observableArrayList(); private final ObservableList queries = FXCollections.observableArrayList(); private final ObservableList databases = FXCollections.observableArrayList(); + // Hold the complement of databases for the selector private final SimpleStringProperty directory = new SimpleStringProperty(); + private Study study; + public ManageStudyDefinitionViewModel(ImportFormatPreferences importFormatPreferences, + ImporterPreferences importerPreferences) { + databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) + .stream() + .map(SearchBasedFetcher::getName) + // The user wants to select specific fetchers + // The fetcher summarizing ALL fetchers can be emulated by selecting ALL fetchers (which happens rarely when doing an SLR) + .filter(name -> !name.equals(CompositeSearchBasedFetcher.FETCHER_NAME)) + .map(name -> { + boolean enabled = DEFAULT_SELECTION.contains(name); + return new StudyDatabaseItem(name, enabled); + }) + .toList()); + } + public ManageStudyDefinitionViewModel(Study study, Path studyDirectory, ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { - if (Objects.isNull(study)) { - // Add databases that are selected by default first. - databases.addAll(DEFAULT_SELECTION - .stream() - .map(studyDatabase -> new StudyDatabaseItem(studyDatabase.getName(), true)) - .toList()); - - computeNonSelectedDatabases(importFormatPreferences, importerPreferences); - return; - } this.study = study; title.setValue(study.getTitle()); authors.addAll(study.getAuthors()); @@ -80,7 +98,8 @@ private void computeNonSelectedDatabases(ImportFormatPreferences importFormatPre .stream() .map(SearchBasedFetcher::getName) .map(s -> new StudyDatabaseItem(s, false)) - .filter(studyDatabase -> !databases.contains(studyDatabase)).toList()); + .filter(studyDatabase -> !databases.contains(studyDatabase)) + .toList()); } public StringProperty getTitle() { diff --git a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java index 50ceda09143..e29630af152 100644 --- a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java +++ b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java @@ -1,5 +1,7 @@ package org.jabref.gui.slr; +import java.util.Objects; + import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; @@ -10,7 +12,7 @@ public class StudyDatabaseItem { private final BooleanProperty enabled; public StudyDatabaseItem(String name, boolean enabled) { - this.name = new SimpleStringProperty(name); + this.name = new SimpleStringProperty(Objects.requireNonNull(name)); this.enabled = new SimpleBooleanProperty(enabled); } @@ -38,6 +40,14 @@ public BooleanProperty enabledProperty() { return enabled; } + @Override + public String toString() { + return "StudyDatabaseItem{" + + "name=" + name.get() + + ", enabled=" + enabled.get() + + '}'; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -46,19 +56,12 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - StudyDatabaseItem that = (StudyDatabaseItem) o; - - if (isEnabled() != that.isEnabled()) { - return false; - } - return getName() != null ? getName().equals(that.getName()) : that.getName() == null; + return getName().equals(that.getName()) && (isEnabled() == (that.isEnabled())); } @Override public int hashCode() { - int result = getName() != null ? getName().hashCode() : 0; - result = 31 * result + (isEnabled() ? 1 : 0); - return result; + return Objects.hash(getName(), isEnabled()); } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java index 10ba0e1b1b4..5fd153a07f2 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java @@ -19,6 +19,8 @@ public class ACMPortalFetcher implements SearchBasedParserFetcher { + public static final String FETCHER_NAME = "ACM Portal"; + private static final String SEARCH_URL = "https://dl.acm.org/action/doSearch"; public ACMPortalFetcher() { @@ -28,7 +30,7 @@ public ACMPortalFetcher() { @Override public String getName() { - return "ACM Portal"; + return FETCHER_NAME; } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java index 97506c284a6..bee6f3c7fc9 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java @@ -17,6 +17,8 @@ public class CompositeSearchBasedFetcher implements SearchBasedFetcher { + public static final String FETCHER_NAME = "SearchAll"; + private static final Logger LOGGER = LoggerFactory.getLogger(CompositeSearchBasedFetcher.class); private final Set fetchers; @@ -36,7 +38,7 @@ public CompositeSearchBasedFetcher(Set searchBasedFetchers, @Override public String getName() { - return "SearchAll"; + return FETCHER_NAME; } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java index d961ce0b3bc..19d1d67ec1a 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java @@ -33,6 +33,7 @@ * @see Basic API documentation */ public class DBLPFetcher implements SearchBasedParserFetcher { + public static final String FETCHER_NAME = "DBLP"; private static final String BASIC_SEARCH_URL = "https://dblp.org/search/publ/api"; @@ -76,7 +77,7 @@ public void doPostCleanup(BibEntry entry) { @Override public String getName() { - return "DBLP"; + return FETCHER_NAME; } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java index 3ca57ff3cbf..fe9860c3f44 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java @@ -48,9 +48,9 @@ */ public class IEEE implements FulltextFetcher, PagedSearchBasedParserFetcher, CustomizableKeyFetcher { - private static final Logger LOGGER = LoggerFactory.getLogger(IEEE.class); + public static final String FETCHER_NAME = "IEEEXplore"; - private static final String FETCHER_NAME = "IEEEXplore"; + private static final Logger LOGGER = LoggerFactory.getLogger(IEEE.class); private static final String STAMP_BASE_STRING_DOCUMENT = "/stamp/stamp.jsp?tp=&arnumber="; private static final Pattern STAMP_PATTERN = Pattern.compile("(/stamp/stamp.jsp\\?t?p?=?&?arnumber=[0-9]+)"); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java index d0aa60e4494..e1764120e14 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java @@ -40,13 +40,14 @@ */ public class SpringerFetcher implements PagedSearchBasedParserFetcher, CustomizableKeyFetcher { + public static final String FETCHER_NAME = "Springer"; + private static final Logger LOGGER = LoggerFactory.getLogger(SpringerFetcher.class); private static final String API_URL = "https://api.springernature.com/meta/v1/json"; private static final String API_KEY = new BuildInfo().springerNatureAPIKey; // Springer query using the parameter 'q=doi:10.1007/s11276-008-0131-4s=1' will respond faster private static final String TEST_URL_WITHOUT_API_KEY = "https://api.springernature.com/meta/v1/json?q=doi:10.1007/s11276-008-0131-4s=1&p=1&api_key="; - private static final String FETCHER_NAME = "Springer"; private final ImporterPreferences importerPreferences; diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java b/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java index 78a7a420718..769e7f6c200 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java @@ -27,12 +27,13 @@ * Uses Springer API, see https://dev.springer.com */ public class SpringerLink implements FulltextFetcher { + public static final String FETCHER_NAME = "Springer"; + private static final Logger LOGGER = LoggerFactory.getLogger(SpringerLink.class); private static final String API_URL = "https://api.springer.com/meta/v1/json"; private static final String API_KEY = new BuildInfo().springerNatureAPIKey; private static final String CONTENT_HOST = "link.springer.com"; - private static final String FETCHER_NAME = "Springer"; private final ImporterPreferences importerPreferences; diff --git a/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java new file mode 100644 index 00000000000..5b64a0a425c --- /dev/null +++ b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java @@ -0,0 +1,55 @@ +package org.jabref.gui.slr; + +import java.util.List; + +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; +import org.jabref.logic.importer.ImportFormatPreferences; +import org.jabref.logic.importer.ImporterPreferences; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Answers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class ManageStudyDefinitionViewModelTest { + private ImportFormatPreferences importFormatPreferences; + private ImporterPreferences importerPreferences; + + @BeforeEach + void setUp() { + // code taken from org.jabref.logic.importer.WebFetchersTest.setUp + importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); + importerPreferences = mock(ImporterPreferences.class); + FieldContentFormatterPreferences fieldContentFormatterPreferences = mock(FieldContentFormatterPreferences.class); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn(fieldContentFormatterPreferences); + } + + @Test + public void constructorFillsDatabasesCorrectly() { + ManageStudyDefinitionViewModel manageStudyDefinitionViewModel = new ManageStudyDefinitionViewModel(importFormatPreferences, importerPreferences); + assertEquals(List.of( + new StudyDatabaseItem("ACM Portal", true), + new StudyDatabaseItem("ArXiv", false), + new StudyDatabaseItem("Biodiversity Heritage", false), + new StudyDatabaseItem("CiteSeerX", false), + new StudyDatabaseItem("Collection of Computer Science Bibliographies", false), + new StudyDatabaseItem("Crossref", false), + new StudyDatabaseItem("DBLP", true), + new StudyDatabaseItem("DOAB", false), + new StudyDatabaseItem("DOAJ", false), + new StudyDatabaseItem("GVK", false), + new StudyDatabaseItem("IEEEXplore", true), + new StudyDatabaseItem("INSPIRE", false), + new StudyDatabaseItem("MathSciNet", false), + new StudyDatabaseItem("Medline/PubMed", false), + new StudyDatabaseItem("ResearchGate", false), + new StudyDatabaseItem("SAO/NASA ADS", false), + new StudyDatabaseItem("SemanticScholar", false), + new StudyDatabaseItem("Springer", true), + new StudyDatabaseItem("zbMATH", false) + ), manageStudyDefinitionViewModel.getDatabases()); + } +} From 2d216dda1c2fcdcee1f49b21fe022c8aabf48c6c Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 3 Sep 2022 12:01:55 +0200 Subject: [PATCH 4/8] Create constructor for existing studies --- .../slr/ManageStudyDefinitionViewModel.java | 56 ++++++------- .../org/jabref/gui/slr/StudyDatabaseItem.java | 5 ++ .../java/org/jabref/model/study/Study.java | 2 +- .../org/jabref/model/study/StudyDatabase.java | 3 + .../ManageStudyDefinitionViewModelTest.java | 83 ++++++++++++++----- 5 files changed, 99 insertions(+), 50 deletions(-) diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java index e07886d2ed3..3f87b2232c3 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java @@ -53,8 +53,9 @@ public class ManageStudyDefinitionViewModel { // Hold the complement of databases for the selector private final SimpleStringProperty directory = new SimpleStringProperty(); - private Study study; - + /** + * Constructor for a new study + */ public ManageStudyDefinitionViewModel(ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) @@ -70,36 +71,35 @@ public ManageStudyDefinitionViewModel(ImportFormatPreferences importFormatPrefer .toList()); } + /** + * Constructor for an existing study + * + * @param study The study to initialize the UI from + * @param studyDirectory The path where the study resides + */ public ManageStudyDefinitionViewModel(Study study, Path studyDirectory, ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { - this.study = study; + // copy the content of the study object into the UI fields + authors.addAll(Objects.requireNonNull(study).getAuthors()); title.setValue(study.getTitle()); - authors.addAll(study.getAuthors()); researchQuestions.addAll(study.getResearchQuestions()); queries.addAll(study.getQueries().stream().map(StudyQuery::getQuery).toList()); - - // Currently, modifying an existing study is not possible. But this code first adds all databases that are - // enabled for an existing Study object as enabled entries to the table and afterwards populates the table with - // all other available databases. - databases.addAll(study.getDatabases() - .stream() - .map(studyDatabase -> new StudyDatabaseItem(studyDatabase.getName(), studyDatabase.isEnabled())) - .toList()); - computeNonSelectedDatabases(importFormatPreferences, importerPreferences); - if (!Objects.isNull(studyDirectory)) { - this.directory.set(studyDirectory.toString()); - } - } - - private void computeNonSelectedDatabases(ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { + List studyDatabases = study.getDatabases(); databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) .stream() .map(SearchBasedFetcher::getName) - .map(s -> new StudyDatabaseItem(s, false)) - .filter(studyDatabase -> !databases.contains(studyDatabase)) + // The user wants to select specific fetchers + // The fetcher summarizing ALL fetchers can be emulated by selecting ALL fetchers (which happens rarely when doing an SLR) + .filter(name -> !name.equals(CompositeSearchBasedFetcher.FETCHER_NAME)) + .map(name -> { + boolean enabled = studyDatabases.contains(new StudyDatabase(name, true)); + return new StudyDatabaseItem(name, enabled); + }) .toList()); + + this.directory.set(Objects.requireNonNull(studyDirectory).toString()); } public StringProperty getTitle() { @@ -148,14 +148,12 @@ public void addQuery(String query) { } public SlrStudyAndDirectory saveStudy() { - if (Objects.isNull(study)) { - study = new Study(); - } - study.setTitle(title.getValueSafe()); - study.setAuthors(authors); - study.setResearchQuestions(researchQuestions); - study.setQueries(queries.stream().map(StudyQuery::new).collect(Collectors.toList())); - study.setDatabases(databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).filter(StudyDatabase::isEnabled).collect(Collectors.toList())); + Study study = new Study( + authors, + title.getValueSafe(), + researchQuestions, + queries.stream().map(StudyQuery::new).collect(Collectors.toList()), + databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).filter(StudyDatabase::isEnabled).collect(Collectors.toList())); Path studyDirectory = null; try { studyDirectory = Path.of(directory.getValueSafe()); diff --git a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java index e29630af152..175c1cf03bb 100644 --- a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java +++ b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java @@ -7,6 +7,11 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import org.jabref.model.study.StudyDatabase; + +/** + * View representation of {@link StudyDatabase} + */ public class StudyDatabaseItem { private final StringProperty name; private final BooleanProperty enabled; diff --git a/src/main/java/org/jabref/model/study/Study.java b/src/main/java/org/jabref/model/study/Study.java index 1c85a1d77c2..3748f0962bc 100644 --- a/src/main/java/org/jabref/model/study/Study.java +++ b/src/main/java/org/jabref/model/study/Study.java @@ -35,7 +35,7 @@ public Study(List authors, String title, List researchQuestions, /** * Used for Jackson deserialization */ - public Study() { + private Study() { } public List getAuthors() { diff --git a/src/main/java/org/jabref/model/study/StudyDatabase.java b/src/main/java/org/jabref/model/study/StudyDatabase.java index ac71a7160c2..375b59fb57c 100644 --- a/src/main/java/org/jabref/model/study/StudyDatabase.java +++ b/src/main/java/org/jabref/model/study/StudyDatabase.java @@ -1,5 +1,8 @@ package org.jabref.model.study; +/** + * data model for the view {@link org.jabref.gui.slr.StudyDatabaseItem} + */ public class StudyDatabase { private String name; private boolean enabled; diff --git a/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java index 5b64a0a425c..f6f9d927909 100644 --- a/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java +++ b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java @@ -1,13 +1,17 @@ package org.jabref.gui.slr; +import java.nio.file.Path; import java.util.List; import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.ImporterPreferences; +import org.jabref.model.study.Study; +import org.jabref.model.study.StudyDatabase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.Answers; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -28,28 +32,67 @@ void setUp() { } @Test - public void constructorFillsDatabasesCorrectly() { + public void emptyStudyConstructorFillsDatabasesCorrectly() { ManageStudyDefinitionViewModel manageStudyDefinitionViewModel = new ManageStudyDefinitionViewModel(importFormatPreferences, importerPreferences); assertEquals(List.of( - new StudyDatabaseItem("ACM Portal", true), - new StudyDatabaseItem("ArXiv", false), - new StudyDatabaseItem("Biodiversity Heritage", false), - new StudyDatabaseItem("CiteSeerX", false), - new StudyDatabaseItem("Collection of Computer Science Bibliographies", false), - new StudyDatabaseItem("Crossref", false), - new StudyDatabaseItem("DBLP", true), - new StudyDatabaseItem("DOAB", false), - new StudyDatabaseItem("DOAJ", false), - new StudyDatabaseItem("GVK", false), - new StudyDatabaseItem("IEEEXplore", true), - new StudyDatabaseItem("INSPIRE", false), - new StudyDatabaseItem("MathSciNet", false), - new StudyDatabaseItem("Medline/PubMed", false), - new StudyDatabaseItem("ResearchGate", false), - new StudyDatabaseItem("SAO/NASA ADS", false), - new StudyDatabaseItem("SemanticScholar", false), - new StudyDatabaseItem("Springer", true), - new StudyDatabaseItem("zbMATH", false) + new StudyDatabaseItem("ACM Portal", true), + new StudyDatabaseItem("ArXiv", false), + new StudyDatabaseItem("Biodiversity Heritage", false), + new StudyDatabaseItem("CiteSeerX", false), + new StudyDatabaseItem("Collection of Computer Science Bibliographies", false), + new StudyDatabaseItem("Crossref", false), + new StudyDatabaseItem("DBLP", true), + new StudyDatabaseItem("DOAB", false), + new StudyDatabaseItem("DOAJ", false), + new StudyDatabaseItem("GVK", false), + new StudyDatabaseItem("IEEEXplore", true), + new StudyDatabaseItem("INSPIRE", false), + new StudyDatabaseItem("MathSciNet", false), + new StudyDatabaseItem("Medline/PubMed", false), + new StudyDatabaseItem("ResearchGate", false), + new StudyDatabaseItem("SAO/NASA ADS", false), + new StudyDatabaseItem("SemanticScholar", false), + new StudyDatabaseItem("Springer", true), + new StudyDatabaseItem("zbMATH", false) + ), manageStudyDefinitionViewModel.getDatabases()); + } + + @Test + public void studyConstructorFillsDatabasesCorrectly(@TempDir Path tempDir) { + List databases = List.of( + new StudyDatabase("ACM Portal", true)); + Study study = new Study( + List.of("Name"), + "title", + List.of("Q1"), + List.of(), + databases + ); + ManageStudyDefinitionViewModel manageStudyDefinitionViewModel = new ManageStudyDefinitionViewModel( + study, + tempDir, + importFormatPreferences, + importerPreferences); + assertEquals(List.of( + new StudyDatabaseItem("ACM Portal", true), + new StudyDatabaseItem("ArXiv", false), + new StudyDatabaseItem("Biodiversity Heritage", false), + new StudyDatabaseItem("CiteSeerX", false), + new StudyDatabaseItem("Collection of Computer Science Bibliographies", false), + new StudyDatabaseItem("Crossref", false), + new StudyDatabaseItem("DBLP", false), + new StudyDatabaseItem("DOAB", false), + new StudyDatabaseItem("DOAJ", false), + new StudyDatabaseItem("GVK", false), + new StudyDatabaseItem("IEEEXplore", false), + new StudyDatabaseItem("INSPIRE", false), + new StudyDatabaseItem("MathSciNet", false), + new StudyDatabaseItem("Medline/PubMed", false), + new StudyDatabaseItem("ResearchGate", false), + new StudyDatabaseItem("SAO/NASA ADS", false), + new StudyDatabaseItem("SemanticScholar", false), + new StudyDatabaseItem("Springer", false), + new StudyDatabaseItem("zbMATH", false) ), manageStudyDefinitionViewModel.getDatabases()); } } From 0d6584b8646800871e8b5cf1b7dda13c38bfdb7f Mon Sep 17 00:00:00 2001 From: Kevin Klein Date: Sat, 3 Sep 2022 12:43:41 +0200 Subject: [PATCH 5/8] Fix behaviour of study database table --- .../gui/slr/ManageStudyDefinitionView.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index eceb736802b..dffcee6f761 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -21,6 +21,7 @@ import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; import org.jabref.gui.DialogService; import org.jabref.gui.icon.IconTheme; @@ -28,6 +29,7 @@ import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.ValueTableCellFactory; +import org.jabref.gui.util.ViewModelTableRowFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.study.Study; import org.jabref.preferences.PreferencesService; @@ -164,17 +166,35 @@ private void initQueriesTab() { } private void initDatabasesTab() { + new ViewModelTableRowFactory() + .withOnMouseClickedEvent((entry, event) -> { + if (event.getButton() == MouseButton.PRIMARY) { + entry.setEnabled(!entry.isEnabled()); + } + }) + .install(databaseTable); + databaseColumn.setReorderable(false); databaseColumn.setCellFactory(TextFieldTableCell.forTableColumn()); databaseEnabledColumn.setResizable(false); databaseEnabledColumn.setReorderable(false); - databaseEnabledColumn.setCellValueFactory(param -> param.getValue().enabledProperty()); databaseEnabledColumn.setCellFactory(CheckBoxTableCell.forTableColumn(databaseEnabledColumn)); + databaseEnabledColumn.setCellValueFactory(param -> param.getValue().enabledProperty()); + databaseColumn.setEditable(false); databaseColumn.setCellValueFactory(param -> param.getValue().nameProperty()); databaseTable.setItems(viewModel.getDatabases()); + + /* + databaseTable.getSelectionModel().selectedItemProperty().addListener( + (obs, oldSelection, newSelection) -> { + if (newSelection != null) { + newSelection.setEnabled(!newSelection.isEnabled()); + } + } + );*/ } private void setupCommonPropertiesForTables(Node addControl, From addf806e6d3b76c7c3d4853b6ea1b10f61896b64 Mon Sep 17 00:00:00 2001 From: Kevin Klein Date: Sat, 3 Sep 2022 12:50:31 +0200 Subject: [PATCH 6/8] Update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23f76110599..912e581893b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,11 +26,11 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We changed the button label from "Return to JabRef" to "Return to library" to better indicate the purpose of the action. - We removed "last-search-date" from the SLR feature, because the last-search-date can be deducted from the git logs. - We reworked the External Changes Resolver dialog. [#9021](https://github.com/JabRef/jabref/pull/9021) - +- We reworked the Define study parameters dialog. [#9123](https://github.com/JabRef/jabref/pull/9123) ### Fixed -- We fixed an issue where the possibilty to generate a subdatabase from an aux file was writing empty files when called from the commandline [#9115](https://github.com/JabRef/jabref/issues/9115), [forum#3516](https://discourse.jabref.org/t/export-subdatabase-from-aux-file-on-macos-command-line/3516) +- We fixed an issue where the possibility to generate a subdatabase from an aux file was writing empty files when called from the commandline [#9115](https://github.com/JabRef/jabref/issues/9115), [forum#3516](https://discourse.jabref.org/t/export-subdatabase-from-aux-file-on-macos-command-line/3516) - We fixed the display of issue, number, eid and pages fields in the entry preview. [#8607](https://github.com/JabRef/jabref/pull/8607), [#8372](https://github.com/JabRef/jabref/issues/8372), [Koppor#514](https://github.com/koppor/jabref/issues/514), [forum#2390](https://discourse.jabref.org/t/unable-to-edit-my-bibtex-file-that-i-used-before-vers-5-1/2390), [forum#3462](https://discourse.jabref.org/t/jabref-5-6-need-help-with-export-from-jabref-to-microsoft-word-entry-preview-of-apa-7-not-rendering-correctly/3462) - We fixed the page ranges checker to detect article numbers in the pages field (used at [Check Integrity](https://docs.jabref.org/finding-sorting-and-cleaning-entries/checkintegrity)). [#8607](https://github.com/JabRef/jabref/pull/8607) - The [HtmlToLaTeXFormatter](https://docs.jabref.org/finding-sorting-and-cleaning-entries/saveactions#html-to-latex) keeps single `<` characters. From 38efd952987f6e3ed89cf43569b6e906b1b05574 Mon Sep 17 00:00:00 2001 From: Kevin Klein Date: Sat, 3 Sep 2022 13:00:14 +0200 Subject: [PATCH 7/8] Resolve comments --- .../org/jabref/gui/slr/ManageStudyDefinitionView.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index dffcee6f761..ebd7e89619f 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -186,15 +186,6 @@ private void initDatabasesTab() { databaseColumn.setCellValueFactory(param -> param.getValue().nameProperty()); databaseTable.setItems(viewModel.getDatabases()); - - /* - databaseTable.getSelectionModel().selectedItemProperty().addListener( - (obs, oldSelection, newSelection) -> { - if (newSelection != null) { - newSelection.setEnabled(!newSelection.isEnabled()); - } - } - );*/ } private void setupCommonPropertiesForTables(Node addControl, From e9925c2569c492cf6cba37e1b79869036d0755ce Mon Sep 17 00:00:00 2001 From: Kevin Klein <38384885+0x002A@users.noreply.github.com> Date: Sat, 3 Sep 2022 13:00:40 +0200 Subject: [PATCH 8/8] Update src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java Co-authored-by: Christoph --- src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java index 175c1cf03bb..c6c77eaaf31 100644 --- a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java +++ b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java @@ -62,7 +62,7 @@ public boolean equals(Object o) { return false; } StudyDatabaseItem that = (StudyDatabaseItem) o; - return getName().equals(that.getName()) && (isEnabled() == (that.isEnabled())); + return Object.equals(getName(),that.getName()) && Object.equals(isEnabled(), that.isEnabled()); } @Override