diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 0e5c84ee85d..ec5a32d541b 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -60,7 +60,7 @@ import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.undo.UndoableInsertEntry; -import org.jabref.gui.undo.UndoableRemoveEntry; +import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.worker.SendAsEMailAction; import org.jabref.logic.citationstyle.CitationStyleCache; @@ -80,15 +80,15 @@ import org.jabref.model.database.KeyCollisionException; import org.jabref.model.database.event.BibDatabaseContextChangedEvent; import org.jabref.model.database.event.CoarseChangeFilter; +import org.jabref.model.database.event.EntriesRemovedEvent; import org.jabref.model.database.event.EntryAddedEvent; -import org.jabref.model.database.event.EntryRemovedEvent; import org.jabref.model.database.shared.DatabaseLocation; import org.jabref.model.database.shared.DatabaseSynchronizer; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FileFieldParser; import org.jabref.model.entry.LinkedFile; +import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.EntryChangedEvent; -import org.jabref.model.entry.event.EntryEventSource; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.field.SpecialField; @@ -408,19 +408,9 @@ private void delete(boolean cut, List entries) { return; } - NamedCompound compound; - if (cut) { - compound = new NamedCompound((entries.size() > 1 ? Localization.lang("cut entries") : Localization.lang("cut entry"))); - } else { - compound = new NamedCompound((entries.size() > 1 ? Localization.lang("delete entries") : Localization.lang("delete entry"))); - } - for (BibEntry entry : entries) { - compound.addEdit(new UndoableRemoveEntry(bibDatabaseContext.getDatabase(), entry)); - bibDatabaseContext.getDatabase().removeEntry(entry); - ensureNotShowingBottomPanel(entry); - } - compound.end(); - getUndoManager().addEdit(compound); + getUndoManager().addEdit(new UndoableRemoveEntries(bibDatabaseContext.getDatabase(), entries, cut)); + bibDatabaseContext.getDatabase().removeEntries(entries); + ensureNotShowingBottomPanel(entries); markBaseChanged(); this.output(formatOutputMessage(cut ? Localization.lang("Cut") : Localization.lang("Deleted"), entries.size())); @@ -892,10 +882,13 @@ public void entryEditorClosing() { } /** - * Closes the entry editor if it is showing the given entry. + * Closes the entry editor if it is showing any of the given entries. */ - private void ensureNotShowingBottomPanel(BibEntry entry) { - if (((mode == BasePanelMode.SHOWING_EDITOR) && (entryEditor.getEntry() == entry))) { + private void ensureNotShowingBottomPanel(List entriesToCheck) { + + // This method is not able to close the bottom pane currently + + if ((mode == BasePanelMode.SHOWING_EDITOR) && (entriesToCheck.contains(entryEditor.getEntry()))) { closeBottomPane(); } } @@ -1128,7 +1121,7 @@ private class GroupTreeListener { @Subscribe public void listen(EntryAddedEvent addedEntryEvent) { // if the added entry is an undo don't add it to the current group - if (addedEntryEvent.getEntryEventSource() == EntryEventSource.UNDO) { + if (addedEntryEvent.getEntriesEventSource() == EntriesEventSource.UNDO) { return; } @@ -1144,8 +1137,8 @@ public void listen(EntryAddedEvent addedEntryEvent) { private class EntryRemovedListener { @Subscribe - public void listen(EntryRemovedEvent entryRemovedEvent) { - ensureNotShowingBottomPanel(entryRemovedEvent.getBibEntry()); + public void listen(EntriesRemovedEvent entriesRemovedEvent) { + ensureNotShowingBottomPanel(entriesRemovedEvent.getBibEntries()); } } @@ -1183,7 +1176,7 @@ public void listen(EntryChangedEvent entryChangedEvent) { } @Subscribe - public void listen(EntryRemovedEvent removedEntryEvent) { + public void listen(EntriesRemovedEvent removedEntriesEvent) { // IMO only used to update the status (found X entries) DefaultTaskExecutor.runInJavaFXThread(() -> frame.getGlobalSearchBar().performSearch()); } diff --git a/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java b/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java index f07dcbe28c9..22e7b0f4dcb 100644 --- a/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java @@ -6,7 +6,7 @@ import org.jabref.JabRefGUI; import org.jabref.gui.preview.PreviewViewer; import org.jabref.gui.undo.NamedCompound; -import org.jabref.gui.undo.UndoableRemoveEntry; +import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; @@ -40,7 +40,7 @@ public EntryDeleteChangeViewModel(BibEntry memEntry, BibEntry tmpEntry) { @Override public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { database.getDatabase().removeEntry(memEntry); - undoEdit.addEdit(new UndoableRemoveEntry(database.getDatabase(), memEntry)); + undoEdit.addEdit(new UndoableRemoveEntries(database.getDatabase(), memEntry)); } @Override diff --git a/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java b/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java index e19cb675914..113fe4f1d2e 100644 --- a/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java +++ b/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -23,7 +22,7 @@ import org.jabref.gui.duplicationFinder.DuplicateResolverDialog.DuplicateResolverType; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertEntry; -import org.jabref.gui.undo.UndoableRemoveEntry; +import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.logic.bibtex.DuplicateCheck; @@ -162,10 +161,8 @@ private void handleDuplicates(DuplicateSearchResult result) { final NamedCompound compoundEdit = new NamedCompound(Localization.lang("duplicate removal")); // Now, do the actual removal: if (!result.getToRemove().isEmpty()) { - for (BibEntry entry : result.getToRemove()) { - panel.getDatabase().removeEntry(entry); - compoundEdit.addEdit(new UndoableRemoveEntry(panel.getDatabase(), entry)); - } + compoundEdit.addEdit(new UndoableRemoveEntries(panel.getDatabase(), result.getToRemove())); + panel.getDatabase().removeEntries(result.getToRemove()); panel.markBaseChanged(); } // and adding merged entries: @@ -196,8 +193,8 @@ class DuplicateSearchResult { private int duplicates = 0; - public synchronized Collection getToRemove() { - return toRemove.values(); + public synchronized List getToRemove() { + return new ArrayList<>(toRemove.values()); } public synchronized List getToAdd() { diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java index 71bae10e73b..77709406ea8 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java @@ -1,5 +1,6 @@ package org.jabref.gui.mergeentries; +import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -10,7 +11,7 @@ import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertEntry; -import org.jabref.gui.undo.UndoableRemoveEntry; +import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; @@ -57,10 +58,9 @@ public void execute() { // Remove the other two entries and add them to the undo stack (which is not working...) NamedCompound ce = new NamedCompound(Localization.lang("Merge entries")); ce.addEdit(new UndoableInsertEntry(basePanel.getDatabase(), mergedEntry.get())); - ce.addEdit(new UndoableRemoveEntry(basePanel.getDatabase(), one)); - basePanel.getDatabase().removeEntry(one); - ce.addEdit(new UndoableRemoveEntry(basePanel.getDatabase(), two)); - basePanel.getDatabase().removeEntry(two); + List entriesToRemove = Arrays.asList(one, two); + ce.addEdit(new UndoableRemoveEntries(basePanel.getDatabase(), entriesToRemove)); + basePanel.getDatabase().removeEntries(entriesToRemove); ce.end(); basePanel.getUndoManager().addEdit(ce); diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index 8d178b74350..4924bc9f2cc 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java @@ -16,14 +16,14 @@ import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; import org.jabref.gui.mergeentries.MergeEntriesDialog; -import org.jabref.gui.undo.UndoableRemoveEntry; +import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.l10n.Localization; import org.jabref.logic.shared.DBMSConnection; import org.jabref.logic.shared.DBMSConnectionProperties; import org.jabref.logic.shared.DBMSSynchronizer; import org.jabref.logic.shared.event.ConnectionLostEvent; -import org.jabref.logic.shared.event.SharedEntryNotPresentEvent; +import org.jabref.logic.shared.event.SharedEntriesNotPresentEvent; import org.jabref.logic.shared.event.UpdateRefusedEvent; import org.jabref.logic.shared.exception.InvalidDBMSConnectionPropertiesException; import org.jabref.logic.shared.exception.NotASharedDatabaseException; @@ -119,13 +119,13 @@ public void listen(UpdateRefusedEvent updateRefusedEvent) { } @Subscribe - public void listen(SharedEntryNotPresentEvent event) { + public void listen(SharedEntriesNotPresentEvent event) { BasePanel panel = jabRefFrame.getCurrentBasePanel(); EntryEditor entryEditor = panel.getEntryEditor(); - panel.getUndoManager().addEdit(new UndoableRemoveEntry(panel.getDatabase(), event.getBibEntry())); + panel.getUndoManager().addEdit(new UndoableRemoveEntries(panel.getDatabase(), event.getBibEntries())); - if (Objects.nonNull(entryEditor) && (entryEditor.getEntry() == event.getBibEntry())) { + if (Objects.nonNull(entryEditor) && (event.getBibEntries().contains(entryEditor.getEntry()))) { dialogService.showInformationDialogAndWait(Localization.lang("Shared entry is no longer present"), Localization.lang("The entry you currently work on has been deleted on the shared side.") diff --git a/src/main/java/org/jabref/gui/undo/UndoableRemoveEntries.java b/src/main/java/org/jabref/gui/undo/UndoableRemoveEntries.java new file mode 100644 index 00000000000..f0605b9b585 --- /dev/null +++ b/src/main/java/org/jabref/gui/undo/UndoableRemoveEntries.java @@ -0,0 +1,84 @@ +package org.jabref.gui.undo; + +import java.util.Collections; +import java.util.List; + +import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabase; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.event.EntriesEventSource; +import org.jabref.model.strings.StringUtil; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class represents the removal of entries. The constructor needs + * references to the database, the entries, and the map of open entry editors. + * TODO is this map still being used? + * The latter to be able to close the entry's editor if it is opened after + * an undo, and the removal is then undone. + */ +public class UndoableRemoveEntries extends AbstractUndoableJabRefEdit { + + private static final Logger LOGGER = LoggerFactory.getLogger(UndoableRemoveEntries.class); + private final BibDatabase base; + private final List entries; + private final boolean cut; + + public UndoableRemoveEntries(BibDatabase base, BibEntry entry) { + this(base, Collections.singletonList(entry)); + } + + public UndoableRemoveEntries(BibDatabase base, List entries) { + this(base, entries, false); + } + + public UndoableRemoveEntries(BibDatabase base, List entries, boolean cut) { + this.base = base; + this.entries = entries; + this.cut = cut; + } + + @Override + public String getPresentationName() { + if (cut) { + if (entries.size() > 1) { + return Localization.lang("cut entries"); + } else if (entries.size() == 1) { + return Localization.lang("cut entry %0", + StringUtil.boldHTML(entries.get(0).getCiteKeyOptional().orElse(Localization.lang("undefined")))); + } else { + return null; + } + } else { + if (entries.size() > 1) { + return Localization.lang("remove entries"); + } else if (entries.size() == 1) { + return Localization.lang("remove entry %0", + StringUtil.boldHTML(entries.get(0).getCiteKeyOptional().orElse(Localization.lang("undefined")))); + } else { + return null; + } + } + } + + @Override + public void undo() { + super.undo(); + base.insertEntries(entries, EntriesEventSource.UNDO); + } + + @Override + public void redo() { + super.redo(); + + // Redo the change. + try { + base.removeEntries(entries); + } catch (Throwable ex) { + LOGGER.warn("Problem to redo `remove entries`", ex); + } + } + +} diff --git a/src/main/java/org/jabref/gui/undo/UndoableRemoveEntry.java b/src/main/java/org/jabref/gui/undo/UndoableRemoveEntry.java deleted file mode 100644 index 21362cbfac8..00000000000 --- a/src/main/java/org/jabref/gui/undo/UndoableRemoveEntry.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.jabref.gui.undo; - -import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEventSource; -import org.jabref.model.strings.StringUtil; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class represents the removal of an entry. The constructor needs - * references to the database, the entry, and the map of open entry editors. - * The latter to be able to close the entry's editor if it is opened after - * an undo, and the removal is then undone. - */ -public class UndoableRemoveEntry extends AbstractUndoableJabRefEdit { - - private static final Logger LOGGER = LoggerFactory.getLogger(UndoableRemoveEntry.class); - private final BibDatabase base; - private final BibEntry entry; - - public UndoableRemoveEntry(BibDatabase base, BibEntry entry) { - this.base = base; - this.entry = entry; - } - - @Override - public String getPresentationName() { - return Localization.lang("remove entry %0", - StringUtil.boldHTML(entry.getCiteKeyOptional().orElse(Localization.lang("undefined")))); - } - - @Override - public void undo() { - super.undo(); - base.insertEntry(entry, EntryEventSource.UNDO); - } - - @Override - public void redo() { - super.redo(); - - // Redo the change. - try { - base.removeEntry(entry); - } catch (Throwable ex) { - LOGGER.warn("Problem to redo `remove entry`", ex); - } - } - -} diff --git a/src/main/java/org/jabref/logic/citationstyle/CitationStyleCache.java b/src/main/java/org/jabref/logic/citationstyle/CitationStyleCache.java index 7a95b42e8bb..0e9a546b2c3 100644 --- a/src/main/java/org/jabref/logic/citationstyle/CitationStyleCache.java +++ b/src/main/java/org/jabref/logic/citationstyle/CitationStyleCache.java @@ -3,7 +3,7 @@ import java.util.Objects; import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.database.event.EntryRemovedEvent; +import org.jabref.model.database.event.EntriesRemovedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.event.EntryChangedEvent; @@ -62,11 +62,13 @@ public void listen(EntryChangedEvent entryChangedEvent) { } /** - * removes the citation of the removed entry as it's not needed anymore + * removes the citation of the removed entries as they are not needed anymore */ @Subscribe - public void listen(EntryRemovedEvent entryRemovedEvent) { - citationStyleCache.invalidate(entryRemovedEvent.getBibEntry()); + public void listen(EntriesRemovedEvent entriesRemovedEvent) { + for (BibEntry entry : entriesRemovedEvent.getBibEntries()) { + citationStyleCache.invalidate(entry); + } } } } diff --git a/src/main/java/org/jabref/logic/shared/DBMSProcessor.java b/src/main/java/org/jabref/logic/shared/DBMSProcessor.java index 9192c915d21..1d6c58829b0 100644 --- a/src/main/java/org/jabref/logic/shared/DBMSProcessor.java +++ b/src/main/java/org/jabref/logic/shared/DBMSProcessor.java @@ -22,7 +22,7 @@ import org.jabref.model.database.shared.DatabaseConnection; import org.jabref.model.database.shared.DatabaseConnectionProperties; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEventSource; +import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.types.EntryTypeFactory; @@ -475,7 +475,7 @@ public List getSharedEntries(List sharedIDs) { String value = selectEntryResultSet.getString("VALUE"); if (value != null) { - bibEntry.setField(FieldFactory.parseField(selectEntryResultSet.getString("NAME")), value, EntryEventSource.SHARED); + bibEntry.setField(FieldFactory.parseField(selectEntryResultSet.getString("NAME")), value, EntriesEventSource.SHARED); } } } catch (SQLException e) { diff --git a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java index 3bec291c816..f8216a2fdef 100644 --- a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java +++ b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java @@ -14,21 +14,21 @@ import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.util.MetaDataParser; import org.jabref.logic.shared.event.ConnectionLostEvent; -import org.jabref.logic.shared.event.SharedEntryNotPresentEvent; +import org.jabref.logic.shared.event.SharedEntriesNotPresentEvent; import org.jabref.logic.shared.event.UpdateRefusedEvent; import org.jabref.logic.shared.exception.OfflineLockException; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.database.event.EntriesRemovedEvent; import org.jabref.model.database.event.EntryAddedEvent; -import org.jabref.model.database.event.EntryRemovedEvent; import org.jabref.model.database.shared.DatabaseConnection; import org.jabref.model.database.shared.DatabaseConnectionProperties; import org.jabref.model.database.shared.DatabaseNotSupportedException; import org.jabref.model.database.shared.DatabaseSynchronizer; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEvent; -import org.jabref.model.entry.event.EntryEventSource; +import org.jabref.model.entry.event.EntriesEvent; +import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.FieldChangedEvent; import org.jabref.model.metadata.MetaData; import org.jabref.model.metadata.event.MetaDataChangedEvent; @@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory; /** - * Synchronizes the shared or local databases with their opposite side. Local changes are pushed by {@link EntryEvent} + * Synchronizes the shared or local databases with their opposite side. Local changes are pushed by {@link EntriesEvent} * using Google's Guava EventBus. */ public class DBMSSynchronizer implements DatabaseSynchronizer { @@ -76,7 +76,7 @@ public DBMSSynchronizer(BibDatabaseContext bibDatabaseContext, Character keyword */ @Subscribe public void listen(EntryAddedEvent event) { - // While synchronizing the local database (see synchronizeLocalDatabase() below), some EntryEvents may be posted. + // While synchronizing the local database (see synchronizeLocalDatabase() below), some EntriesEvents may be posted. // In this case DBSynchronizer should not try to insert the bibEntry entry again (but it would not harm). if (isEventSourceAccepted(event) && checkCurrentConnection()) { synchronizeLocalMetaData(); @@ -92,7 +92,7 @@ public void listen(EntryAddedEvent event) { */ @Subscribe public void listen(FieldChangedEvent event) { - // While synchronizing the local database (see synchronizeLocalDatabase() below), some EntryEvents may be posted. + // While synchronizing the local database (see synchronizeLocalDatabase() below), some EntriesEvents may be posted. // In this case DBSynchronizer should not try to update the bibEntry entry again (but it would not harm). if (isPresentLocalBibEntry(event.getBibEntry()) && isEventSourceAccepted(event) && checkCurrentConnection()) { synchronizeLocalMetaData(); @@ -103,16 +103,21 @@ public void listen(FieldChangedEvent event) { } /** - * Listening method. Deletes the given {@link BibEntry} from shared database. + * Listening method. Deletes the given list of {@link BibEntry} from shared database. * * @param event {@link EntryRemovedEvent} object */ + + // This has not been made parallel yet - hence the for loop - that will take more effort @Subscribe - public void listen(EntryRemovedEvent event) { - // While synchronizing the local database (see synchronizeLocalDatabase() below), some EntryEvents may be posted. + public void listen(EntriesRemovedEvent event) { + // While synchronizing the local database (see synchronizeLocalDatabase() below), some EntriesEvents may be posted. // In this case DBSynchronizer should not try to delete the bibEntry entry again (but it would not harm). if (isEventSourceAccepted(event) && checkCurrentConnection()) { - dbmsProcessor.removeEntry(event.getBibEntry()); + List entries = event.getBibEntries(); + for (BibEntry entry : entries) { + dbmsProcessor.removeEntry(entry); + } synchronizeLocalMetaData(); synchronizeLocalDatabase(); // Pull changes for the case that there where some } @@ -186,19 +191,19 @@ public void synchronizeLocalDatabase() { Optional sharedEntry = dbmsProcessor.getSharedEntry(idVersionEntry.getKey()); if (sharedEntry.isPresent()) { // update fields - localEntry.setType(sharedEntry.get().getType(), EntryEventSource.SHARED); + localEntry.setType(sharedEntry.get().getType(), EntriesEventSource.SHARED); localEntry.getSharedBibEntryData() .setVersion(sharedEntry.get().getSharedBibEntryData().getVersion()); - // copy remote values to local entry sharedEntry.get().getFieldMap().forEach( - (field, value) -> localEntry.setField(field, value, EntryEventSource.SHARED) + // copy remote values to local entry + (field, value) -> localEntry.setField(field, value, EntriesEventSource.SHARED) ); // locally remove not existing fields localEntry.getFields().stream() .filter(field -> !sharedEntry.get().hasField(field)) .forEach( - field -> localEntry.clearField(field, EntryEventSource.SHARED) + field -> localEntry.clearField(field, EntriesEventSource.SHARED) ); } } @@ -210,7 +215,7 @@ public void synchronizeLocalDatabase() { } for (BibEntry bibEntry : dbmsProcessor.getSharedEntries(entriesToDrag)) { - bibDatabase.insertEntry(bibEntry, EntryEventSource.SHARED); + bibDatabase.insertEntry(bibEntry, EntriesEventSource.SHARED); } } @@ -221,8 +226,8 @@ public void synchronizeLocalDatabase() { * @param sharedIDs Set of all IDs which are present on shared database */ private void removeNotSharedEntries(List localEntries, Set sharedIDs) { - for (int i = 0; i < localEntries.size(); i++) { - BibEntry localEntry = localEntries.get(i); + List entriesToRemove = new ArrayList<>(); + for (BibEntry localEntry : localEntries) { boolean match = false; for (int sharedID : sharedIDs) { if (localEntry.getSharedBibEntryData().getSharedID() == sharedID) { @@ -231,11 +236,13 @@ private void removeNotSharedEntries(List localEntries, Set sh } } if (!match) { - eventBus.post(new SharedEntryNotPresentEvent(localEntry)); - bibDatabase.removeEntry(localEntry, EntryEventSource.SHARED); // Should not reach the listeners above. - i--; // due to index shift on localEntries + entriesToRemove.add(localEntry); } } + if (!entriesToRemove.isEmpty()) { + eventBus.post(new SharedEntriesNotPresentEvent(entriesToRemove)); + } + bibDatabase.removeEntries(entriesToRemove, EntriesEventSource.SHARED); // Should not reach the listeners above. } /** @@ -343,15 +350,15 @@ public boolean checkCurrentConnection() { } /** - * Checks whether the {@link EntryEventSource} of an {@link EntryEvent} is crucial for this class. + * Checks whether the {@link EntriesEventSource} of an {@link EntriesEvent} is crucial for this class. * - * @param event An {@link EntryEvent} + * @param event An {@link EntriesEvent} * @return true if the event is able to trigger operations in {@link DBMSSynchronizer}, else * false */ - public boolean isEventSourceAccepted(EntryEvent event) { - EntryEventSource eventSource = event.getEntryEventSource(); - return ((eventSource == EntryEventSource.LOCAL) || (eventSource == EntryEventSource.UNDO)); + public boolean isEventSourceAccepted(EntriesEvent event) { + EntriesEventSource eventSource = event.getEntriesEventSource(); + return ((eventSource == EntriesEventSource.LOCAL) || (eventSource == EntriesEventSource.UNDO)); } @Override diff --git a/src/main/java/org/jabref/logic/shared/event/SharedEntriesNotPresentEvent.java b/src/main/java/org/jabref/logic/shared/event/SharedEntriesNotPresentEvent.java new file mode 100644 index 00000000000..6972e60e90d --- /dev/null +++ b/src/main/java/org/jabref/logic/shared/event/SharedEntriesNotPresentEvent.java @@ -0,0 +1,25 @@ +package org.jabref.logic.shared.event; + +import java.util.List; + +import org.jabref.model.entry.BibEntry; + +/** + * This event is fired when the user tries to push changes of one or more obsolete + * {@link BibEntry} to the server. + */ +public class SharedEntriesNotPresentEvent { + + private final List bibEntries; + + /** + * @param bibEntries Affected {@link BibEntry} + */ + public SharedEntriesNotPresentEvent(List bibEntries) { + this.bibEntries = bibEntries; + } + + public List getBibEntries() { + return this.bibEntries; + } +} diff --git a/src/main/java/org/jabref/logic/shared/event/SharedEntryNotPresentEvent.java b/src/main/java/org/jabref/logic/shared/event/SharedEntryNotPresentEvent.java deleted file mode 100644 index f2f6b61b069..00000000000 --- a/src/main/java/org/jabref/logic/shared/event/SharedEntryNotPresentEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.jabref.logic.shared.event; - -import org.jabref.model.entry.BibEntry; - -/** - * A new {@link SharedEntryNotPresentEvent} is fired, when the user tries to push changes of an obsolete - * {@link BibEntry} to the server. - */ -public class SharedEntryNotPresentEvent { - - private final BibEntry bibEntry; - - /** - * @param bibEntry Affected {@link BibEntry} - */ - public SharedEntryNotPresentEvent(BibEntry bibEntry) { - this.bibEntry = bibEntry; - } - - public BibEntry getBibEntry() { - return this.bibEntry; - } -} diff --git a/src/main/java/org/jabref/model/cleanup/FieldFormatterCleanup.java b/src/main/java/org/jabref/model/cleanup/FieldFormatterCleanup.java index e38d77b2de4..5965ed3fdb2 100644 --- a/src/main/java/org/jabref/model/cleanup/FieldFormatterCleanup.java +++ b/src/main/java/org/jabref/model/cleanup/FieldFormatterCleanup.java @@ -9,7 +9,7 @@ import org.jabref.model.FieldChange; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEventSource; +import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.field.InternalField; @@ -63,7 +63,7 @@ private List cleanupSingleField(Field fieldKey, BibEntry entry) { entry.clearField(fieldKey); newValue = null; } else { - entry.setField(fieldKey, newValue, EntryEventSource.SAVE_ACTION); + entry.setField(fieldKey, newValue, EntriesEventSource.SAVE_ACTION); } FieldChange change = new FieldChange(entry, fieldKey, oldValue, newValue); return Collections.singletonList(change); diff --git a/src/main/java/org/jabref/model/database/BibDatabase.java b/src/main/java/org/jabref/model/database/BibDatabase.java index e23e2b7d33a..9e3485bc602 100644 --- a/src/main/java/org/jabref/model/database/BibDatabase.java +++ b/src/main/java/org/jabref/model/database/BibDatabase.java @@ -22,13 +22,13 @@ import javafx.collections.ObservableList; import org.jabref.model.database.event.AllInsertsFinishedEvent; +import org.jabref.model.database.event.EntriesRemovedEvent; import org.jabref.model.database.event.EntryAddedEvent; -import org.jabref.model.database.event.EntryRemovedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibtexString; import org.jabref.model.entry.Month; +import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.EntryChangedEvent; -import org.jabref.model.entry.event.EntryEventSource; import org.jabref.model.entry.event.FieldChangedEvent; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; @@ -193,7 +193,7 @@ public synchronized Optional getEntryById(String id) { * @throws KeyCollisionException thrown if the entry id ({@link BibEntry#getId()}) is already present in the database */ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionException { - return insertEntry(entry, EntryEventSource.LOCAL); + return insertEntry(entry, EntriesEventSource.LOCAL); } /** @@ -204,20 +204,20 @@ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionExcep * @param eventSource Source the event is sent from * @return false if the insert was done without a duplicate warning */ - public synchronized boolean insertEntry(BibEntry entry, EntryEventSource eventSource) throws KeyCollisionException { + public synchronized boolean insertEntry(BibEntry entry, EntriesEventSource eventSource) throws KeyCollisionException { insertEntries(Collections.singletonList(entry), eventSource); return duplicationChecker.isDuplicateCiteKeyExisting(entry); } public synchronized void insertEntries(BibEntry... entries) throws KeyCollisionException { - insertEntries(Arrays.asList(entries), EntryEventSource.LOCAL); + insertEntries(Arrays.asList(entries), EntriesEventSource.LOCAL); } public synchronized void insertEntries(List entries) throws KeyCollisionException { - insertEntries(entries, EntryEventSource.LOCAL); + insertEntries(entries, EntriesEventSource.LOCAL); } - private synchronized void insertEntries(List newEntries, EntryEventSource eventSource) throws KeyCollisionException { + public synchronized void insertEntries(List newEntries, EntriesEventSource eventSource) throws KeyCollisionException { Objects.requireNonNull(newEntries); BibEntry firstEntry = null; @@ -242,29 +242,41 @@ private synchronized void insertEntries(List newEntries, EntryEventSou } } + public synchronized void removeEntry(BibEntry bibEntry) { + removeEntries(Collections.singletonList(bibEntry)); + } + + public synchronized void removeEntry(BibEntry bibEntry, EntriesEventSource eventSource) { + removeEntries(Collections.singletonList(bibEntry), eventSource); + } + /** - * Removes the given entry. - * The Entry is removed based on the id {@link BibEntry#id} - * @param toBeDeleted Entry to delete + * Removes the given entries. + * The entries removed based on the id {@link BibEntry#id} + * @param toBeDeleted Entries to delete */ - public synchronized void removeEntry(BibEntry toBeDeleted) { - removeEntry(toBeDeleted, EntryEventSource.LOCAL); + public synchronized void removeEntries(List toBeDeleted) { + removeEntries(toBeDeleted, EntriesEventSource.LOCAL); } /** - * Removes the given entry. - * The Entry is removed based on the id {@link BibEntry#id} + * Removes the given entries. + * The entries are removed based on the id {@link BibEntry#id} * * @param toBeDeleted Entry to delete * @param eventSource Source the event is sent from */ - public synchronized void removeEntry(BibEntry toBeDeleted, EntryEventSource eventSource) { + public synchronized void removeEntries(List toBeDeleted, EntriesEventSource eventSource) { Objects.requireNonNull(toBeDeleted); - boolean anyRemoved = entries.removeIf(entry -> entry.getId().equals(toBeDeleted.getId())); + List ids = new ArrayList<>(); + for (BibEntry entry : toBeDeleted) { + ids.add(entry.getId()); + } + boolean anyRemoved = entries.removeIf(entry -> ids.contains(entry.getId())); if (anyRemoved) { - internalIDs.remove(toBeDeleted.getId()); - eventBus.post(new EntryRemovedEvent(toBeDeleted, eventSource)); + internalIDs.removeAll(ids); + eventBus.post(new EntriesRemovedEvent(toBeDeleted, eventSource)); } } @@ -304,12 +316,12 @@ public synchronized void addString(BibtexString string) throws KeyCollisionExcep /** * Replaces the existing lists of BibTexString with the given one - * No Duplicate checks are performed + * Duplicates throw KeyCollisionException * @param stringsToAdd The collection of strings to set */ - public void setStrings(Collection stringsToAdd) { - Map strs = stringsToAdd.stream().collect(Collectors.toConcurrentMap(BibtexString::getId, (bibtexStr) -> bibtexStr)); - bibtexStrings = strs; + public void setStrings(List stringsToAdd) { + bibtexStrings = new ConcurrentHashMap<>(); + stringsToAdd.forEach(this::addString); } /** diff --git a/src/main/java/org/jabref/model/database/DuplicationChecker.java b/src/main/java/org/jabref/model/database/DuplicationChecker.java index 1fccdd45023..732338e5cbf 100644 --- a/src/main/java/org/jabref/model/database/DuplicationChecker.java +++ b/src/main/java/org/jabref/model/database/DuplicationChecker.java @@ -1,11 +1,12 @@ package org.jabref.model.database; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; +import org.jabref.model.database.event.EntriesRemovedEvent; import org.jabref.model.database.event.EntryAddedEvent; -import org.jabref.model.database.event.EntryRemovedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.event.FieldChangedEvent; import org.jabref.model.entry.field.InternalField; @@ -92,10 +93,13 @@ public void listen(FieldChangedEvent fieldChangedEvent) { } @Subscribe - public void listen(EntryRemovedEvent entryRemovedEvent) { - Optional citeKey = entryRemovedEvent.getBibEntry().getCiteKeyOptional(); - if (citeKey.isPresent()) { - removeKeyFromSet(citeKey.get()); + public void listen(EntriesRemovedEvent entriesRemovedEvent) { + List entries = entriesRemovedEvent.getBibEntries(); + for (BibEntry entry : entries) { + Optional citeKey = entry.getCiteKeyOptional(); + if (citeKey.isPresent()) { + removeKeyFromSet(citeKey.get()); + } } } diff --git a/src/main/java/org/jabref/model/database/KeyChangeListener.java b/src/main/java/org/jabref/model/database/KeyChangeListener.java index 9ddb9fdfe28..6ba90976b0c 100644 --- a/src/main/java/org/jabref/model/database/KeyChangeListener.java +++ b/src/main/java/org/jabref/model/database/KeyChangeListener.java @@ -3,8 +3,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Optional; -import org.jabref.model.database.event.EntryRemovedEvent; +import org.jabref.model.database.event.EntriesRemovedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.event.FieldChangedEvent; import org.jabref.model.entry.field.Field; @@ -32,8 +33,12 @@ public void listen(FieldChangedEvent event) { } @Subscribe - public void listen(EntryRemovedEvent event) { - event.getBibEntry().getCiteKeyOptional().ifPresent(oldKey -> updateEntryLinks(null, oldKey)); + public void listen(EntriesRemovedEvent event) { + List entries = event.getBibEntries(); + for (BibEntry entry : entries) { + Optional citeKey = entry.getCiteKeyOptional(); + citeKey.ifPresent(oldkey -> updateEntryLinks(null, oldkey)); + } } private void updateEntryLinks(String newKey, String oldKey) { diff --git a/src/main/java/org/jabref/model/database/event/AllInsertsFinishedEvent.java b/src/main/java/org/jabref/model/database/event/AllInsertsFinishedEvent.java index 07ba5c92cef..eb9bc84df00 100644 --- a/src/main/java/org/jabref/model/database/event/AllInsertsFinishedEvent.java +++ b/src/main/java/org/jabref/model/database/event/AllInsertsFinishedEvent.java @@ -1,27 +1,29 @@ package org.jabref.model.database.event; +import java.util.Collections; + import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEvent; -import org.jabref.model.entry.event.EntryEventSource; +import org.jabref.model.entry.event.EntriesEvent; +import org.jabref.model.entry.event.EntriesEventSource; /** * {@link AllInsertsFinishedEvent} is fired when insertion of {@link BibEntry} to the {@link BibDatabase} was finished. */ -public class AllInsertsFinishedEvent extends EntryEvent { +public class AllInsertsFinishedEvent extends EntriesEvent { /** * @param bibEntry the entry which has been added */ public AllInsertsFinishedEvent(BibEntry bibEntry) { - super(bibEntry); + super(Collections.singletonList(bibEntry)); } /** * @param bibEntry BibEntry object which has been added. * @param location Location affected by this event */ - public AllInsertsFinishedEvent(BibEntry bibEntry, EntryEventSource location) { - super(bibEntry, location); + public AllInsertsFinishedEvent(BibEntry bibEntry, EntriesEventSource location) { + super(Collections.singletonList(bibEntry), location); } } diff --git a/src/main/java/org/jabref/model/database/event/BibDatabaseContextChangedEvent.java b/src/main/java/org/jabref/model/database/event/BibDatabaseContextChangedEvent.java index 5e67bea2bb0..15acdced130 100644 --- a/src/main/java/org/jabref/model/database/event/BibDatabaseContextChangedEvent.java +++ b/src/main/java/org/jabref/model/database/event/BibDatabaseContextChangedEvent.java @@ -1,11 +1,10 @@ package org.jabref.model.database.event; -import org.jabref.model.entry.event.EntryEvent; import org.jabref.model.groups.event.GroupUpdatedEvent; import org.jabref.model.metadata.event.MetaDataChangedEvent; /** - * This Event is automatically fired at the same time as {@link EntryEvent}, {@link GroupUpdatedEvent} or {@link MetaDataChangedEvent}. + * This Event is automatically fired at the same time as {@link EntriesEvent}, {@link GroupUpdatedEvent} or {@link MetaDataChangedEvent}. */ public class BibDatabaseContextChangedEvent { // no data diff --git a/src/main/java/org/jabref/model/database/event/EntriesRemovedEvent.java b/src/main/java/org/jabref/model/database/event/EntriesRemovedEvent.java new file mode 100644 index 00000000000..aa10fe2fe8a --- /dev/null +++ b/src/main/java/org/jabref/model/database/event/EntriesRemovedEvent.java @@ -0,0 +1,31 @@ +package org.jabref.model.database.event; + +import java.util.List; + +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.event.EntriesEvent; +import org.jabref.model.entry.event.EntriesEventSource; + +/** + * EntriesRemovedEvent is fired when at least one BibEntry is removed + * from the database. + */ + +public class EntriesRemovedEvent extends EntriesEvent { + + /** + * @param bibEntries List of BibEntry object which have been removed. + */ + public EntriesRemovedEvent(List bibEntries) { + super(bibEntries); + } + + /** + * @param bibEntries List of BibEntry object which have been removed. + * @param location Location affected by this event + */ + public EntriesRemovedEvent(List bibEntries, EntriesEventSource location) { + super(bibEntries, location); + } + +} diff --git a/src/main/java/org/jabref/model/database/event/EntryAddedEvent.java b/src/main/java/org/jabref/model/database/event/EntryAddedEvent.java index f94575b66ca..fbd6655e88e 100644 --- a/src/main/java/org/jabref/model/database/event/EntryAddedEvent.java +++ b/src/main/java/org/jabref/model/database/event/EntryAddedEvent.java @@ -1,27 +1,29 @@ package org.jabref.model.database.event; +import java.util.Collections; + import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEvent; -import org.jabref.model.entry.event.EntryEventSource; +import org.jabref.model.entry.event.EntriesEvent; +import org.jabref.model.entry.event.EntriesEventSource; /** * {@link EntryAddedEvent} is fired when a new {@link BibEntry} was added to the {@link BibDatabase}. */ -public class EntryAddedEvent extends EntryEvent { +public class EntryAddedEvent extends EntriesEvent { /** * @param bibEntry the entry which has been added */ public EntryAddedEvent(BibEntry bibEntry) { - super(bibEntry); + super(Collections.singletonList(bibEntry)); } /** * @param bibEntry BibEntry object which has been added. * @param location Location affected by this event */ - public EntryAddedEvent(BibEntry bibEntry, EntryEventSource location) { - super(bibEntry, location); + public EntryAddedEvent(BibEntry bibEntry, EntriesEventSource location) { + super(Collections.singletonList(bibEntry), location); } } diff --git a/src/main/java/org/jabref/model/database/event/EntryRemovedEvent.java b/src/main/java/org/jabref/model/database/event/EntryRemovedEvent.java deleted file mode 100644 index 37d292e6e78..00000000000 --- a/src/main/java/org/jabref/model/database/event/EntryRemovedEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.jabref.model.database.event; - -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEvent; -import org.jabref.model.entry.event.EntryEventSource; - -/** - * RemovedEntryEvent is fired when a BibEntry was removed - * from the database. - */ - -public class EntryRemovedEvent extends EntryEvent { - - /** - * @param bibEntry BibEntry object which has been removed. - */ - public EntryRemovedEvent(BibEntry bibEntry) { - super(bibEntry); - } - - /** - * @param bibEntry BibEntry object which has been removed. - * @param location Location affected by this event - */ - public EntryRemovedEvent(BibEntry bibEntry, EntryEventSource location) { - super(bibEntry, location); - } - -} diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index a600d5892a3..a9afe9ba0e8 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -23,7 +23,7 @@ import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; -import org.jabref.model.entry.event.EntryEventSource; +import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.FieldAddedOrRemovedEvent; import org.jabref.model.entry.event.FieldChangedEvent; import org.jabref.model.entry.field.Field; @@ -343,13 +343,13 @@ public ObjectProperty typeProperty() { * Sets this entry's type. */ public Optional setType(EntryType type) { - return setType(type, EntryEventSource.LOCAL); + return setType(type, EntriesEventSource.LOCAL); } /** * Sets this entry's type. */ - public Optional setType(EntryType newType, EntryEventSource eventSource) { + public Optional setType(EntryType newType, EntriesEventSource eventSource) { Objects.requireNonNull(newType); EntryType oldType = type.get(); @@ -510,7 +510,7 @@ public void setField(Map fields) { * @param value The value to set * @param eventSource Source the event is sent from */ - public Optional setField(Field field, String value, EntryEventSource eventSource) { + public Optional setField(Field field, String value, EntriesEventSource eventSource) { Objects.requireNonNull(field, "field name must not be null"); Objects.requireNonNull(value, "field value must not be null"); @@ -545,7 +545,7 @@ public Optional setField(Field field, String value, EntryEventSourc * @param value The value to set. */ public Optional setField(Field field, String value) { - return setField(field, value, EntryEventSource.LOCAL); + return setField(field, value, EntriesEventSource.LOCAL); } /** @@ -555,17 +555,17 @@ public Optional setField(Field field, String value) { * @param field The field to clear. */ public Optional clearField(Field field) { - return clearField(field, EntryEventSource.LOCAL); + return clearField(field, EntriesEventSource.LOCAL); } /** * Remove the mapping for the field name, and notify listeners about - * the change including the {@link EntryEventSource}. + * the change including the {@link EntriesEventSource}. * * @param field the field to clear. * @param eventSource the source a new {@link FieldChangedEvent} should be posten from. */ - public Optional clearField(Field field, EntryEventSource eventSource) { + public Optional clearField(Field field, EntriesEventSource eventSource) { Optional oldValue = getField(field); if (!oldValue.isPresent()) { return Optional.empty(); diff --git a/src/main/java/org/jabref/model/entry/event/EntriesEvent.java b/src/main/java/org/jabref/model/entry/event/EntriesEvent.java new file mode 100644 index 00000000000..b8a2c10e6f2 --- /dev/null +++ b/src/main/java/org/jabref/model/entry/event/EntriesEvent.java @@ -0,0 +1,45 @@ +package org.jabref.model.entry.event; + +import java.util.List; +import java.util.Objects; + +import org.jabref.model.database.event.BibDatabaseContextChangedEvent; +import org.jabref.model.entry.BibEntry; + +/** + * This abstract class pretends a minimal set of attributes and methods + * which an entries event should have. + */ +public abstract class EntriesEvent extends BibDatabaseContextChangedEvent { + + private final List bibEntries; + private final EntriesEventSource location; + + + /** + * @param bibEntries List of BibEntry objects which are involved in this event + */ + public EntriesEvent(List bibEntries) { + this(bibEntries, EntriesEventSource.LOCAL); + } + + /** + * @param bibEntries List of BibEntry objects which are involved in this event + * @param location Location affected by this event + */ + public EntriesEvent(List bibEntries, EntriesEventSource location) { + this.bibEntries = Objects.requireNonNull(bibEntries); + this.location = Objects.requireNonNull(location); + } + + //Temporary fix, while we change to plural entries + public BibEntry getBibEntry() { return this.bibEntries.get(0); } + + public List getBibEntries() { + return this.bibEntries; + } + + public EntriesEventSource getEntriesEventSource() { + return this.location; + } +} diff --git a/src/main/java/org/jabref/model/entry/event/EntriesEventSource.java b/src/main/java/org/jabref/model/entry/event/EntriesEventSource.java new file mode 100644 index 00000000000..ede1ea5285c --- /dev/null +++ b/src/main/java/org/jabref/model/entry/event/EntriesEventSource.java @@ -0,0 +1,11 @@ +package org.jabref.model.entry.event; + +/** + * This enum represents the context EntriesEvents were sent from. + */ +public enum EntriesEventSource { + LOCAL, + SHARED, + UNDO, + SAVE_ACTION +} diff --git a/src/main/java/org/jabref/model/entry/event/EntryChangedEvent.java b/src/main/java/org/jabref/model/entry/event/EntryChangedEvent.java index 149379f5e55..cf83402d498 100644 --- a/src/main/java/org/jabref/model/entry/event/EntryChangedEvent.java +++ b/src/main/java/org/jabref/model/entry/event/EntryChangedEvent.java @@ -1,26 +1,28 @@ package org.jabref.model.entry.event; +import java.util.Collections; + import org.jabref.model.entry.BibEntry; /** * EntryChangedEvent is fired when a BibEntry has been changed. */ -public class EntryChangedEvent extends EntryEvent { +public class EntryChangedEvent extends EntriesEvent { /** * @param bibEntry BibEntry object the changes were applied on. */ public EntryChangedEvent(BibEntry bibEntry) { - super(bibEntry); + super(Collections.singletonList(bibEntry)); } /** * @param bibEntry BibEntry object the changes were applied on. * @param location Location affected by this event */ - public EntryChangedEvent(BibEntry bibEntry, EntryEventSource location) { - super(bibEntry, location); + public EntryChangedEvent(BibEntry bibEntry, EntriesEventSource location) { + super(Collections.singletonList(bibEntry), location); } } diff --git a/src/main/java/org/jabref/model/entry/event/EntryEvent.java b/src/main/java/org/jabref/model/entry/event/EntryEvent.java deleted file mode 100644 index 921e54f4ad1..00000000000 --- a/src/main/java/org/jabref/model/entry/event/EntryEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.jabref.model.entry.event; - -import java.util.Objects; - -import org.jabref.model.database.event.BibDatabaseContextChangedEvent; -import org.jabref.model.entry.BibEntry; - -/** - * This abstract class pretends a minimal set of attributes and methods - * which an entry event should have. - */ -public abstract class EntryEvent extends BibDatabaseContextChangedEvent { - - private final BibEntry bibEntry; - private final EntryEventSource location; - - - /** - * @param bibEntry BibEntry object which is involved in this event - */ - public EntryEvent(BibEntry bibEntry) { - this(bibEntry, EntryEventSource.LOCAL); - } - - /** - * @param bibEntry BibEntry object which is involved in this event - * @param location Location affected by this event - */ - public EntryEvent(BibEntry bibEntry, EntryEventSource location) { - this.bibEntry = Objects.requireNonNull(bibEntry); - this.location = Objects.requireNonNull(location); - } - - public BibEntry getBibEntry() { - return this.bibEntry; - } - - public EntryEventSource getEntryEventSource() { - return this.location; - } -} diff --git a/src/main/java/org/jabref/model/entry/event/EntryEventSource.java b/src/main/java/org/jabref/model/entry/event/EntryEventSource.java deleted file mode 100644 index bcf910092f3..00000000000 --- a/src/main/java/org/jabref/model/entry/event/EntryEventSource.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.jabref.model.entry.event; - -/** - * This enum represents the context EntryEvents were sent from. - */ -public enum EntryEventSource { - LOCAL, - SHARED, - UNDO, - SAVE_ACTION -} diff --git a/src/main/java/org/jabref/model/entry/event/FieldAddedOrRemovedEvent.java b/src/main/java/org/jabref/model/entry/event/FieldAddedOrRemovedEvent.java index f346c4e806a..63306f6582d 100644 --- a/src/main/java/org/jabref/model/entry/event/FieldAddedOrRemovedEvent.java +++ b/src/main/java/org/jabref/model/entry/event/FieldAddedOrRemovedEvent.java @@ -4,7 +4,7 @@ public class FieldAddedOrRemovedEvent extends FieldChangedEvent { - public FieldAddedOrRemovedEvent(FieldChange fieldChange, EntryEventSource location) { + public FieldAddedOrRemovedEvent(FieldChange fieldChange, EntriesEventSource location) { super(fieldChange, location); } } diff --git a/src/main/java/org/jabref/model/entry/event/FieldChangedEvent.java b/src/main/java/org/jabref/model/entry/event/FieldChangedEvent.java index b81fb2ced06..90151a111ba 100644 --- a/src/main/java/org/jabref/model/entry/event/FieldChangedEvent.java +++ b/src/main/java/org/jabref/model/entry/event/FieldChangedEvent.java @@ -23,7 +23,7 @@ public class FieldChangedEvent extends EntryChangedEvent { * @param location location Location affected by this event */ public FieldChangedEvent(BibEntry bibEntry, Field field, String newValue, String oldValue, - EntryEventSource location) { + EntriesEventSource location) { super(bibEntry, location); this.field = field; this.newValue = newValue; @@ -47,7 +47,7 @@ public FieldChangedEvent(BibEntry bibEntry, Field field, String newValue, String /** * @param location location Location affected by this event */ - public FieldChangedEvent(FieldChange fieldChange, EntryEventSource location) { + public FieldChangedEvent(FieldChange fieldChange, EntriesEventSource location) { super(fieldChange.getEntry(), location); this.field = fieldChange.getField(); this.newValue = fieldChange.getNewValue(); @@ -56,7 +56,7 @@ public FieldChangedEvent(FieldChange fieldChange, EntryEventSource location) { } public FieldChangedEvent(FieldChange fieldChange) { - this(fieldChange, EntryEventSource.LOCAL); + this(fieldChange, EntriesEventSource.LOCAL); } private int computeDelta(String oldValue, String newValue) { diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 0a489731034..0a656074d5c 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -204,7 +204,7 @@ Cut=Cut cut\ entries=cut entries -cut\ entry=cut entry +cut\ entry\ %0=cut entry %0 Library\ encoding=Library encoding @@ -225,12 +225,8 @@ Delete=Delete Delete\ custom\ format=Delete custom format -delete\ entries=delete entries - Delete\ entry=Delete entry -delete\ entry=delete entry - Delete\ multiple\ entries=Delete multiple entries Deleted=Deleted @@ -1640,6 +1636,7 @@ change\ string\ name\ %0\ to\ %1=change string name %0 to %1 change\ type\ of\ entry\ %0\ from\ %1\ to\ %2=change type of entry %0 from %1 to %2 insert\ entry\ %0=insert entry %0 insert\ string\ %0=insert string %0 +remove\ entries=remove entries remove\ entry\ %0=remove entry %0 remove\ string\ %0=remove string %0 undefined=undefined diff --git a/src/test/java/org/jabref/logic/shared/DBMSSynchronizerTest.java b/src/test/java/org/jabref/logic/shared/DBMSSynchronizerTest.java index 2575e069719..ef4fd4acbff 100644 --- a/src/test/java/org/jabref/logic/shared/DBMSSynchronizerTest.java +++ b/src/test/java/org/jabref/logic/shared/DBMSSynchronizerTest.java @@ -21,7 +21,7 @@ import org.jabref.model.database.shared.DBMSType; import org.jabref.model.database.shared.DatabaseNotSupportedException; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.event.EntryEventSource; +import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.StandardEntryType; @@ -79,7 +79,7 @@ public void testEntryAddedEventListener() { bibDatabase.insertEntry(expectedEntry); // should not add into shared database. - bibDatabase.insertEntry(furtherEntry, EntryEventSource.SHARED); + bibDatabase.insertEntry(furtherEntry, EntriesEventSource.SHARED); List actualEntries = dbmsProcessor.getSharedEntries(); @@ -94,7 +94,7 @@ public void testFieldChangedEventListener() { bibDatabase.insertEntry(expectedEntry); expectedEntry.setField(StandardField.AUTHOR, "Brad L and Gilson"); - expectedEntry.setField(StandardField.TITLE, "The micro multiplexer", EntryEventSource.SHARED); + expectedEntry.setField(StandardField.TITLE, "The micro multiplexer", EntriesEventSource.SHARED); List actualEntries = dbmsProcessor.getSharedEntries(); assertEquals(1, actualEntries.size()); @@ -103,7 +103,7 @@ public void testFieldChangedEventListener() { } @Test - public void testEntryRemovedEventListener() { + public void testEntriesRemovedEventListener() { BibEntry bibEntry = getBibEntryExample(1); bibDatabase.insertEntry(bibEntry); @@ -117,7 +117,7 @@ public void testEntryRemovedEventListener() { assertEquals(0, actualEntries.size()); bibDatabase.insertEntry(bibEntry); - bibDatabase.removeEntry(bibEntry, EntryEventSource.SHARED); + bibDatabase.removeEntry(bibEntry, EntriesEventSource.SHARED); actualEntries = dbmsProcessor.getSharedEntries(); assertEquals(1, actualEntries.size()); diff --git a/src/test/java/org/jabref/logic/shared/SynchronizationTestEventListener.java b/src/test/java/org/jabref/logic/shared/SynchronizationTestEventListener.java index efef81b7cbc..539de44ddd9 100644 --- a/src/test/java/org/jabref/logic/shared/SynchronizationTestEventListener.java +++ b/src/test/java/org/jabref/logic/shared/SynchronizationTestEventListener.java @@ -1,6 +1,6 @@ package org.jabref.logic.shared; -import org.jabref.logic.shared.event.SharedEntryNotPresentEvent; +import org.jabref.logic.shared.event.SharedEntriesNotPresentEvent; import org.jabref.logic.shared.event.UpdateRefusedEvent; import org.jabref.testutils.category.DatabaseTest; @@ -9,12 +9,12 @@ @DatabaseTest public class SynchronizationTestEventListener { - private SharedEntryNotPresentEvent sharedEntryNotPresentEvent; + private SharedEntriesNotPresentEvent sharedEntriesNotPresentEvent; private UpdateRefusedEvent updateRefusedEvent; @Subscribe - public void listen(SharedEntryNotPresentEvent event) { - this.sharedEntryNotPresentEvent = event; + public void listen(SharedEntriesNotPresentEvent event) { + this.sharedEntriesNotPresentEvent = event; } @Subscribe @@ -22,8 +22,8 @@ public void listen(UpdateRefusedEvent event) { this.updateRefusedEvent = event; } - public SharedEntryNotPresentEvent getSharedEntryNotPresentEvent() { - return sharedEntryNotPresentEvent; + public SharedEntriesNotPresentEvent getSharedEntriesNotPresentEvent() { + return sharedEntriesNotPresentEvent; } public UpdateRefusedEvent getUpdateRefusedEvent() { diff --git a/src/test/java/org/jabref/logic/shared/SynchronizationTestSimulator.java b/src/test/java/org/jabref/logic/shared/SynchronizationTestSimulator.java index d694a697f7e..78e11ebefa7 100644 --- a/src/test/java/org/jabref/logic/shared/SynchronizationTestSimulator.java +++ b/src/test/java/org/jabref/logic/shared/SynchronizationTestSimulator.java @@ -126,14 +126,14 @@ public void simulateUpdateOnNoLongerExistingEntry() { clientContextA.getDatabase().removeEntry(bibEntryOfClientA); assertFalse(clientContextB.getDatabase().getEntries().isEmpty()); - assertNull(eventListenerB.getSharedEntryNotPresentEvent()); + assertNull(eventListenerB.getSharedEntriesNotPresentEvent()); //client B tries to update the entry BibEntry bibEntryOfClientB = clientContextB.getDatabase().getEntries().get(0); bibEntryOfClientB.setField(StandardField.YEAR, "2009"); // here a new SharedEntryNotPresentEvent has been thrown. In this case the user B would get an pop-up window. - assertNotNull(eventListenerB.getSharedEntryNotPresentEvent()); - assertEquals(bibEntryOfClientB, eventListenerB.getSharedEntryNotPresentEvent().getBibEntry()); + assertNotNull(eventListenerB.getSharedEntriesNotPresentEvent()); + assertEquals(bibEntryOfClientB, eventListenerB.getSharedEntriesNotPresentEvent().getBibEntries()); } @Test diff --git a/src/test/java/org/jabref/model/database/BibDatabaseTest.java b/src/test/java/org/jabref/model/database/BibDatabaseTest.java index 4d747877e31..727436bcac8 100644 --- a/src/test/java/org/jabref/model/database/BibDatabaseTest.java +++ b/src/test/java/org/jabref/model/database/BibDatabaseTest.java @@ -72,6 +72,38 @@ public void removeEntryRemovesEntryFromEntriesList() { assertFalse(database.containsEntryWithId(entry.getId())); } + @Test + public void removeSomeEntriesRemovesThoseEntriesFromEntriesList() { + BibEntry entry1 = new BibEntry(); + BibEntry entry2 = new BibEntry(); + BibEntry entry3 = new BibEntry(); + List allEntries = Arrays.asList(entry1, entry2, entry3); + database.insertEntries(allEntries); + List entriesToDelete = Arrays.asList(entry1, entry3); + database.removeEntries(entriesToDelete); + assertEquals(Collections.singletonList(entry2), database.getEntries()); + assertFalse(database.containsEntryWithId(entry1.getId())); + assertTrue(database.containsEntryWithId(entry2.getId())); + assertFalse(database.containsEntryWithId(entry3.getId())); + } + + @Test + public void removeAllEntriesRemovesAllEntriesFromEntriesList() { + List allEntries = new ArrayList<>(); + BibEntry entry1 = new BibEntry(); + BibEntry entry2 = new BibEntry(); + BibEntry entry3 = new BibEntry(); + allEntries.add(entry1); + allEntries.add(entry2); + allEntries.add(entry3); + + database.removeEntries(allEntries); + assertEquals(Collections.emptyList(), database.getEntries()); + assertFalse(database.containsEntryWithId(entry1.getId())); + assertFalse(database.containsEntryWithId(entry2.getId())); + assertFalse(database.containsEntryWithId(entry3.getId())); + } + @Test public void insertNullEntryThrowsException() { assertThrows(NullPointerException.class, () -> database.insertEntry(null)); @@ -130,12 +162,11 @@ public void setSingleStringAsCollection() { } @Test - public void setStringAsCollectionWithUpdatedContentOverridesString() { + public void setStringAsCollectionWithUpdatedContentThrowsKeyCollisionException() { BibtexString string = new BibtexString("DSP", "Digital Signal Processing"); BibtexString newContent = new BibtexString("DSP", "ABCD"); List strings = Arrays.asList(string, newContent); - database.setStrings(strings); - assertEquals(Optional.of(newContent), database.getStringByName("DSP")); + assertThrows(KeyCollisionException.class, () -> database.setStrings(strings)); } @Test @@ -190,14 +221,16 @@ public void insertMultipleEntriesPostsAddedEntryEvent() { } @Test - public void removeEntryPostsRemovedEntryEvent() { - BibEntry expectedEntry = new BibEntry(); + public void removeEntriesPostsRemovedEntriesEvent() { + BibEntry entry1 = new BibEntry(); + BibEntry entry2 = new BibEntry(); + List expectedEntries = Arrays.asList(entry1, entry2); TestEventListener tel = new TestEventListener(); - database.insertEntry(expectedEntry); + database.insertEntries(expectedEntries); database.registerListener(tel); - database.removeEntry(expectedEntry); - BibEntry actualEntry = tel.getRemovedEntry(); - assertEquals(expectedEntry, actualEntry); + database.removeEntries(expectedEntries); + List actualEntry = tel.getRemovedEntries(); + assertEquals(expectedEntries, actualEntry); } @Test diff --git a/src/test/java/org/jabref/model/database/KeyChangeListenerTest.java b/src/test/java/org/jabref/model/database/KeyChangeListenerTest.java index 09171961256..9fc96615eee 100644 --- a/src/test/java/org/jabref/model/database/KeyChangeListenerTest.java +++ b/src/test/java/org/jabref/model/database/KeyChangeListenerTest.java @@ -1,5 +1,7 @@ package org.jabref.model.database; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import org.jabref.model.entry.BibEntry; @@ -84,8 +86,8 @@ public void testRelatedEntryRemoved() { @Test public void testRelatedAllEntriesRemoved() { - db.removeEntry(entry1); - db.removeEntry(entry3); + List entries = Arrays.asList(entry1, entry3); + db.removeEntries(entries); assertEquals(Optional.empty(), entry2.getField(StandardField.RELATED)); } } diff --git a/src/test/java/org/jabref/model/event/TestEventListener.java b/src/test/java/org/jabref/model/event/TestEventListener.java index 98cd144dd0d..c753bc5cff6 100644 --- a/src/test/java/org/jabref/model/event/TestEventListener.java +++ b/src/test/java/org/jabref/model/event/TestEventListener.java @@ -1,8 +1,10 @@ package org.jabref.model.event; +import java.util.List; + import org.jabref.model.database.event.AllInsertsFinishedEvent; +import org.jabref.model.database.event.EntriesRemovedEvent; import org.jabref.model.database.event.EntryAddedEvent; -import org.jabref.model.database.event.EntryRemovedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.event.EntryChangedEvent; @@ -12,7 +14,7 @@ public class TestEventListener { private BibEntry addedEntry; private BibEntry firstInsertedEntry; - private BibEntry removedEntry; + private List removedEntries; private BibEntry changedEntry; @Subscribe @@ -26,8 +28,8 @@ public void listen(AllInsertsFinishedEvent event) { } @Subscribe - public void listen(EntryRemovedEvent event) { - this.removedEntry = event.getBibEntry(); + public void listen(EntriesRemovedEvent event) { + this.removedEntries = event.getBibEntries(); } @Subscribe @@ -43,8 +45,8 @@ public BibEntry getFirstInsertedEntry() { return firstInsertedEntry; } - public BibEntry getRemovedEntry() { - return removedEntry; + public List getRemovedEntries() { + return removedEntries; } public BibEntry getChangedEntry() {