From b96413db5dc978a5ea52ae2b6bb73d5858a086c7 Mon Sep 17 00:00:00 2001 From: Dominik Voigt Date: Tue, 19 Jan 2021 09:02:37 +0100 Subject: [PATCH 1/6] Add migration to special field --- .../jabref/logic/importer/OpenDatabase.java | 8 +- .../SpecialFieldsToSeparateFields.java | 74 +++++++++++++++ .../SpecialFieldsToSeparateFieldsTest.java | 92 +++++++++++++++++++ 3 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java create mode 100644 src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java diff --git a/src/main/java/org/jabref/logic/importer/OpenDatabase.java b/src/main/java/org/jabref/logic/importer/OpenDatabase.java index 3da89f9a5aa..da945555ad5 100644 --- a/src/main/java/org/jabref/logic/importer/OpenDatabase.java +++ b/src/main/java/org/jabref/logic/importer/OpenDatabase.java @@ -13,6 +13,7 @@ import org.jabref.migrations.ConvertLegacyExplicitGroups; import org.jabref.migrations.ConvertMarkingToGroups; import org.jabref.migrations.PostOpenMigration; +import org.jabref.migrations.SpecialFieldsToSeparateFields; import org.jabref.migrations.TimeStampToDateAddAndModify; import org.jabref.model.entry.BibEntry; import org.jabref.model.util.FileUpdateMonitor; @@ -72,16 +73,17 @@ public static ParserResult loadDatabase(Path fileToOpen, ImportFormatPreferences LOGGER.debug("Synchronized special fields based on keywords"); } - performLoadDatabaseMigrations(result, timestampPreferences); + performLoadDatabaseMigrations(result, timestampPreferences, importFormatPreferences.getKeywordSeparator()); return result; } - private static void performLoadDatabaseMigrations(ParserResult parserResult, TimestampPreferences timestampPreferences) { + private static void performLoadDatabaseMigrations(ParserResult parserResult, TimestampPreferences timestampPreferences, Character keywordDelimited) { List postOpenMigrations = Arrays.asList( new ConvertLegacyExplicitGroups(), new ConvertMarkingToGroups(), - new TimeStampToDateAddAndModify(timestampPreferences) + new TimeStampToDateAddAndModify(timestampPreferences), + new SpecialFieldsToSeparateFields(keywordDelimited) ); for (PostOpenMigration migration : postOpenMigrations) { diff --git a/src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java b/src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java new file mode 100644 index 00000000000..2b24c7f1415 --- /dev/null +++ b/src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java @@ -0,0 +1,74 @@ +package org.jabref.migrations; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.jabref.logic.importer.ParserResult; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.Keyword; +import org.jabref.model.entry.KeywordList; +import org.jabref.model.entry.field.SpecialField; +import org.jabref.model.entry.field.SpecialFieldValue; +import org.jabref.preferences.PreferencesService; + +public class SpecialFieldsToSeparateFields implements PostOpenMigration { + private final KeywordList possibleKeywordsToMigrate; + private final Character keywordDelimiter; + private final Map migrationTable = getMigrationTable(); + + public SpecialFieldsToSeparateFields(Character keywordDelimiter) { + List specialFieldValues = Arrays.asList(SpecialFieldValue.values()); + possibleKeywordsToMigrate = new KeywordList(specialFieldValues.stream() + .map(SpecialFieldValue::getKeyword) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList())); + this.keywordDelimiter = keywordDelimiter; + } + + @Override + public void performMigration(ParserResult parserResult) { + parserResult.getDatabase().getEntries().forEach(this::migrateEntry); + } + + private void migrateEntry(BibEntry entry) { + for (Keyword keyword : possibleKeywordsToMigrate) { + if (entry.getKeywords(keywordDelimiter).contains(keyword) && migrationTable.containsKey(keyword.get())) { + entry.setField(migrationTable.get(keyword.get()), keyword.get()); + } + } + + entry.removeKeywords(possibleKeywordsToMigrate, keywordDelimiter); + } + + /** + * Mapping of special field values (contained in the keywords) to their corresponding special field + */ + private Map getMigrationTable() { + Map map = new HashMap<>(); + map.put("printed", SpecialField.PRINTED); + + map.put("prio1", SpecialField.PRIORITY); + map.put("prio2", SpecialField.PRIORITY); + map.put("prio3", SpecialField.PRIORITY); + + map.put("qualityAssured", SpecialField.QUALITY); + + map.put("rank1", SpecialField.RANKING); + map.put("rank2", SpecialField.RANKING); + map.put("rank3", SpecialField.RANKING); + map.put("rank4", SpecialField.RANKING); + map.put("rank5", SpecialField.RANKING); + + map.put("read", SpecialField.READ_STATUS); + map.put("skimmed", SpecialField.READ_STATUS); + + map.put("relevant", SpecialField.RELEVANCE); + + return map; + } +} diff --git a/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java b/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java new file mode 100644 index 00000000000..6c14105371b --- /dev/null +++ b/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java @@ -0,0 +1,92 @@ +package org.jabref.migrations; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ParserResult; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.SpecialField; +import org.jabref.model.entry.field.SpecialFieldValue; +import org.jabref.model.entry.field.StandardField; +import org.jabref.preferences.PreferencesService; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mockito; + +import static org.junit.jupiter.api.Assertions.*; + +class SpecialFieldsToSeparateFieldsTest { + + @ParameterizedTest + @MethodSource("provideKeywordFieldPairs") + public void migrateToCorrectField(SpecialField expectedField, String fieldInKeyword) { + BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") + .withField(StandardField.KEYWORDS, fieldInKeyword); + + new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); + + assertEquals(fieldInKeyword, entry.getField(expectedField).get()); + } + + @Test + public void noKewordToMigrate() { + BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") + .withField(StandardField.KEYWORDS, "tdd"); + new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); + + assertEquals("JabRef", entry.getField(StandardField.AUTHOR).get()); + assertEquals("tdd", entry.getField(StandardField.KEYWORDS).get()); + } + + @Test + public void migrateMultipleSpecialFields() { + BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") + .withField(StandardField.KEYWORDS, "printed, prio1"); + new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); + + assertEquals("prio1", entry.getField(SpecialField.PRIORITY).get()); + assertEquals("printed", entry.getField(SpecialField.PRINTED).get()); + + } + + @Test + public void migrateSpecialFieldsMixedWithKeyword() { + BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") + .withField(StandardField.KEYWORDS, "tdd, prio1, SE"); + new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); + + assertEquals("prio1", entry.getField(SpecialField.PRIORITY).get()); + assertEquals("tdd, SE", entry.getField(StandardField.KEYWORDS).get()); + + } + + private static Stream provideKeywordFieldPairs() { + return Stream.of( + Arguments.of( + SpecialField.PRINTED, "printed" + ), + Arguments.of( + SpecialField.PRIORITY, "prio1" + ), + Arguments.of( + SpecialField.QUALITY, "qualityAssured" + ), + Arguments.of( + SpecialField.RANKING, "rank2" + ), + Arguments.of( + SpecialField.READ_STATUS, "skimmed" + ), + Arguments.of( + SpecialField.RELEVANCE, "relevant" + ) + ); + } +} + From d55bdcc251eacfcb05d4eb2848b9bd1b58c7cf9d Mon Sep 17 00:00:00 2001 From: Dominik Voigt Date: Tue, 19 Jan 2021 09:03:54 +0100 Subject: [PATCH 2/6] Fix checkstyle --- .../org/jabref/migrations/SpecialFieldsToSeparateFields.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java b/src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java index 2b24c7f1415..06f18823e22 100644 --- a/src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java +++ b/src/main/java/org/jabref/migrations/SpecialFieldsToSeparateFields.java @@ -13,7 +13,6 @@ import org.jabref.model.entry.KeywordList; import org.jabref.model.entry.field.SpecialField; import org.jabref.model.entry.field.SpecialFieldValue; -import org.jabref.preferences.PreferencesService; public class SpecialFieldsToSeparateFields implements PostOpenMigration { private final KeywordList possibleKeywordsToMigrate; From 0658f5859f7dc45f74c530ffbbe8b1c7758c435d Mon Sep 17 00:00:00 2001 From: Dominik Voigt Date: Tue, 19 Jan 2021 09:11:07 +0100 Subject: [PATCH 3/6] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59ab7e13f0e..362b264ee97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve ### Changed - The content of the field `timestamp` is migrated to `creationdate`. In case one configured "udpate timestampe", it is migrated to `modificationdate`. [koppor#130](https://github.com/koppor/jabref/issues/130) +- The JabRef specific meta-data content in the main field such as priorities (prio1, prio2, ...) are migrated to their respective fields. They are removed from the keywords. [#6840]((https://github.com/jabref/jabref/issues/6840)) - We fixed an issue where groups generated from authors' last names did not include all entries of the authors' [#5833](https://github.com/JabRef/jabref/issues/5833) - The export to MS Office XML now uses the month name for the field `MonthAcessed` instead of the two digit number [#7354](https://github.com/JabRef/jabref/issues/7354) From ca62ebd77fc28e429873b6a308f46cf684fb2ef2 Mon Sep 17 00:00:00 2001 From: Dominik Voigt Date: Tue, 19 Jan 2021 09:36:07 +0100 Subject: [PATCH 4/6] Fix checkstyle --- .../migrations/SpecialFieldsToSeparateFieldsTest.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java b/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java index 6c14105371b..a5dbc4a0b10 100644 --- a/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java +++ b/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java @@ -1,25 +1,19 @@ package org.jabref.migrations; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.jabref.logic.importer.ParserResult; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.SpecialFieldValue; import org.jabref.model.entry.field.StandardField; -import org.jabref.preferences.PreferencesService; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mockito; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class SpecialFieldsToSeparateFieldsTest { From 26dfa46beacccb4ec1437eda2a8845c1a918a7ef Mon Sep 17 00:00:00 2001 From: Dominik Voigt Date: Tue, 19 Jan 2021 19:52:43 +0100 Subject: [PATCH 5/6] Update CHANGELOG.md Co-authored-by: Christoph --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 362b264ee97..93d09b0cbbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve ### Changed - The content of the field `timestamp` is migrated to `creationdate`. In case one configured "udpate timestampe", it is migrated to `modificationdate`. [koppor#130](https://github.com/koppor/jabref/issues/130) -- The JabRef specific meta-data content in the main field such as priorities (prio1, prio2, ...) are migrated to their respective fields. They are removed from the keywords. [#6840]((https://github.com/jabref/jabref/issues/6840)) +- The JabRef specific meta-data content in the main field such as priorities (prio1, prio2, ...) are migrated to their respective fields. They are removed from the keywords. [#6840](https://github.com/jabref/jabref/issues/6840) - We fixed an issue where groups generated from authors' last names did not include all entries of the authors' [#5833](https://github.com/JabRef/jabref/issues/5833) - The export to MS Office XML now uses the month name for the field `MonthAcessed` instead of the two digit number [#7354](https://github.com/JabRef/jabref/issues/7354) From be9aca47a533663b9347f09bc036342364bdb849 Mon Sep 17 00:00:00 2001 From: Dominik Voigt Date: Tue, 19 Jan 2021 22:31:44 +0100 Subject: [PATCH 6/6] Readd all changed files --- .../gui/edit/ManageKeywordsViewModel.java | 9 -- .../gui/specialfields/SpecialFieldAction.java | 15 +-- .../specialfields/SpecialFieldViewModel.java | 17 +-- .../jabref/logic/importer/OpenDatabase.java | 9 -- .../specialfields/SpecialFieldsUtils.java | 121 ------------------ .../specialfields/SpecialFieldsUtilsTest.java | 91 ------------- .../SpecialFieldsToSeparateFieldsTest.java | 42 +++--- 7 files changed, 33 insertions(+), 271 deletions(-) delete mode 100644 src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java delete mode 100644 src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java diff --git a/src/main/java/org/jabref/gui/edit/ManageKeywordsViewModel.java b/src/main/java/org/jabref/gui/edit/ManageKeywordsViewModel.java index 7c2809813d7..867eeccea47 100644 --- a/src/main/java/org/jabref/gui/edit/ManageKeywordsViewModel.java +++ b/src/main/java/org/jabref/gui/edit/ManageKeywordsViewModel.java @@ -11,7 +11,6 @@ import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.specialfields.SpecialFieldsUtils; import org.jabref.model.FieldChange; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.Keyword; @@ -105,10 +104,6 @@ public void saveChanges() { return; } - if (preferences.getSpecialFieldsPreferences().isKeywordSyncEnabled() && !keywordsToAdd.isEmpty()) { - SpecialFieldsUtils.synchronizeSpecialFields(keywordsToAdd, keywordsToRemove); - } - NamedCompound ce = updateKeywords(entries, keywordsToAdd, keywordsToRemove); // TODO: bp.getUndoManager().addEdit(ce); } @@ -126,10 +121,6 @@ private NamedCompound updateKeywords(List entries, KeywordList keyword // put keywords back Optional change = entry.putKeywords(keywords, preferences.getKeywordDelimiter()); change.ifPresent(fieldChange -> ce.addEdit(new UndoableFieldChange(fieldChange))); - - if (preferences.getSpecialFieldsPreferences().isKeywordSyncEnabled()) { - SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, preferences.getKeywordDelimiter()); - } } ce.end(); return ce; diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java index 17b04069192..130bf0e3b68 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldAction.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Objects; +import java.util.Optional; import javax.swing.undo.UndoManager; @@ -13,7 +14,7 @@ import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.specialfields.SpecialFieldsUtils; +import org.jabref.logic.util.UpdateField; import org.jabref.model.FieldChange; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.SpecialField; @@ -70,17 +71,9 @@ public void execute() { NamedCompound ce = new NamedCompound(undoText); for (BibEntry bibEntry : bes) { // if (value==null) and then call nullField has been omitted as updatefield also handles value==null - List changes = SpecialFieldsUtils.updateField( - specialField, - value, - bibEntry, - nullFieldIfValueIsTheSame, - preferencesService.getSpecialFieldsPreferences().isKeywordSyncEnabled(), - preferencesService.getKeywordDelimiter()); + Optional change = UpdateField.updateField(bibEntry, specialField, value, nullFieldIfValueIsTheSame); - for (FieldChange change : changes) { - ce.addEdit(new UndoableFieldChange(change)); - } + change.ifPresent(fieldChange -> ce.addEdit(new UndoableFieldChange(fieldChange))); } ce.end(); if (ce.hasEdits()) { diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java index a60f1621bff..596b1848a5a 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldViewModel.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import javax.swing.undo.UndoManager; @@ -13,7 +14,7 @@ import org.jabref.gui.actions.StandardActions; import org.jabref.gui.icon.JabRefIcon; import org.jabref.gui.undo.UndoableFieldChange; -import org.jabref.logic.specialfields.SpecialFieldsUtils; +import org.jabref.logic.util.UpdateField; import org.jabref.model.FieldChange; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.SpecialField; @@ -83,17 +84,9 @@ public List getValues() { } public void setSpecialFieldValue(BibEntry bibEntry, SpecialFieldValue value) { - List changes = SpecialFieldsUtils.updateField( - getField(), - value.getFieldValue().orElse(null), - bibEntry, - getField().isSingleValueField(), - preferencesService.getSpecialFieldsPreferences().isKeywordSyncEnabled(), - preferencesService.getKeywordDelimiter()); - - for (FieldChange change : changes) { - undoManager.addEdit(new UndoableFieldChange(change)); - } + Optional change = UpdateField.updateField(bibEntry, getField(), value.getFieldValue().orElse(null), getField().isSingleValueField()); + + change.ifPresent(fieldChange -> undoManager.addEdit(new UndoableFieldChange(fieldChange))); } public void toggle(BibEntry entry) { diff --git a/src/main/java/org/jabref/logic/importer/OpenDatabase.java b/src/main/java/org/jabref/logic/importer/OpenDatabase.java index da945555ad5..8fec03796a9 100644 --- a/src/main/java/org/jabref/logic/importer/OpenDatabase.java +++ b/src/main/java/org/jabref/logic/importer/OpenDatabase.java @@ -9,13 +9,11 @@ import org.jabref.logic.importer.fileformat.BibtexImporter; import org.jabref.logic.l10n.Localization; import org.jabref.logic.preferences.TimestampPreferences; -import org.jabref.logic.specialfields.SpecialFieldsUtils; import org.jabref.migrations.ConvertLegacyExplicitGroups; import org.jabref.migrations.ConvertMarkingToGroups; import org.jabref.migrations.PostOpenMigration; import org.jabref.migrations.SpecialFieldsToSeparateFields; import org.jabref.migrations.TimeStampToDateAddAndModify; -import org.jabref.model.entry.BibEntry; import org.jabref.model.util.FileUpdateMonitor; import org.slf4j.Logger; @@ -66,13 +64,6 @@ public static ParserResult loadDatabase(Path fileToOpen, ImportFormatPreferences ParserResult result = new BibtexImporter(importFormatPreferences, fileMonitor).importDatabase(fileToOpen, importFormatPreferences.getEncoding()); - if (importFormatPreferences.isKeywordSyncEnabled()) { - for (BibEntry entry : result.getDatabase().getEntries()) { - SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, importFormatPreferences.getKeywordSeparator()); - } - LOGGER.debug("Synchronized special fields based on keywords"); - } - performLoadDatabaseMigrations(result, timestampPreferences, importFormatPreferences.getKeywordSeparator()); return result; diff --git a/src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java b/src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java deleted file mode 100644 index d0df2d63e9d..00000000000 --- a/src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.jabref.logic.specialfields; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import org.jabref.logic.util.UpdateField; -import org.jabref.model.FieldChange; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.Keyword; -import org.jabref.model.entry.KeywordList; -import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.StandardField; - -/** - * @deprecated the class should be refactored and partly integrated into BibEntry - * instead of synchronizing special fields with the keyword field, the BibEntry class should have a method - * setSpecialField(field, newValue, syncToKeyword) which directly performs the correct action - * i.e.sets the field to newValue(in the case syncToKeyword=false)or adds newValue to keywords(sync=true) - */ - -@Deprecated -public class SpecialFieldsUtils { - - /** - * @param field - Field to be handled - * @param value - may be null to state that field should be emptied - * @param entry - BibTeXEntry to be handled - * @param nullFieldIfValueIsTheSame - true: field is nulled if value is the same than the current value in be - */ - public static List updateField(SpecialField field, String value, BibEntry entry, boolean nullFieldIfValueIsTheSame, boolean isKeywordSyncEnabled, Character keywordDelimiter) { - List fieldChanges = new ArrayList<>(); - - UpdateField.updateField(entry, field, value, nullFieldIfValueIsTheSame) - .ifPresent(fieldChanges::add); - // we cannot use "value" here as updateField has side effects: "nullFieldIfValueIsTheSame" nulls the field if value is the same - if (isKeywordSyncEnabled) { - fieldChanges.addAll(SpecialFieldsUtils.exportFieldToKeywords(field, entry, keywordDelimiter)); - } - - return fieldChanges; - } - - private static List exportFieldToKeywords(SpecialField specialField, BibEntry entry, Character keywordDelimiter) { - List fieldChanges = new ArrayList<>(); - - KeywordList keyWords = specialField.getKeyWords(); - Optional newValue = entry.getField(specialField).map(Keyword::new); - newValue.map(value -> entry.replaceKeywords(keyWords, newValue.get(), keywordDelimiter)) - .orElseGet(() -> entry.removeKeywords(keyWords, keywordDelimiter)) - .ifPresent(changeValue -> fieldChanges.add(changeValue)); - - return fieldChanges; - } - - /** - * Update keywords according to values of special fields - */ - public static List syncKeywordsFromSpecialFields(BibEntry entry, Character keywordDelimiter) { - List fieldChanges = new ArrayList<>(); - - for (SpecialField field : SpecialField.values()) { - fieldChanges.addAll(SpecialFieldsUtils.exportFieldToKeywords(field, entry, keywordDelimiter)); - } - - return fieldChanges; - } - - private static List importKeywordsForField(KeywordList keywordList, SpecialField field, BibEntry entry) { - List fieldChanges = new ArrayList<>(); - - KeywordList values = field.getKeyWords(); - Optional newValue = Optional.empty(); - for (Keyword keyword : values) { - if (keywordList.contains(keyword)) { - newValue = Optional.of(keyword); - break; - } - } - - UpdateField.updateNonDisplayableField(entry, field, newValue.map(Keyword::toString).orElse(null)) - .ifPresent(fieldChanges::add); - return fieldChanges; - } - - /** - * Updates special field values according to keywords - */ - public static List syncSpecialFieldsFromKeywords(BibEntry entry, Character keywordDelimiter) { - List fieldChanges = new ArrayList<>(); - if (!entry.hasField(StandardField.KEYWORDS)) { - return fieldChanges; - } - - KeywordList keywordList = entry.getKeywords(keywordDelimiter); - - for (SpecialField field : SpecialField.values()) { - fieldChanges.addAll(SpecialFieldsUtils.importKeywordsForField(keywordList, field, entry)); - } - - return fieldChanges; - } - - public static void synchronizeSpecialFields(KeywordList keywordsToAdd, KeywordList keywordsToRemove) { - // we need to check whether a special field is added - // for each field: - // check if something is added - // if yes, add all keywords of that special fields to the keywords to be removed - - KeywordList clone; - - // Priority - clone = keywordsToAdd.createClone(); - for (SpecialField field : SpecialField.values()) { - clone.retainAll(field.getKeyWords()); - if (!clone.isEmpty()) { - keywordsToRemove.addAll(field.getKeyWords()); - } - } - } -} diff --git a/src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java b/src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java deleted file mode 100644 index 354d49a235e..00000000000 --- a/src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.jabref.logic.specialfields; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import org.jabref.model.FieldChange; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.Keyword; -import org.jabref.model.entry.KeywordList; -import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.StandardField; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class SpecialFieldsUtilsTest { - - @Test - public void syncKeywordsFromSpecialFieldsWritesToKeywords() { - BibEntry entry = new BibEntry(); - entry.setField(SpecialField.RANKING, "rank2"); - SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); - assertEquals(Optional.of("rank2"), entry.getField(StandardField.KEYWORDS)); - } - - @Test - public void syncKeywordsFromSpecialFieldsCausesChange() { - BibEntry entry = new BibEntry(); - entry.setField(SpecialField.RANKING, "rank2"); - List changes = SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); - assertTrue(changes.size() > 0); - } - - @Test - public void syncKeywordsFromSpecialFieldsOverwritesKeywords() { - BibEntry entry = new BibEntry(); - entry.setField(SpecialField.RANKING, "rank2"); - entry.setField(StandardField.KEYWORDS, "rank3"); - SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); - assertEquals(Optional.of("rank2"), entry.getField(StandardField.KEYWORDS)); - } - - @Test - public void syncKeywordsFromSpecialFieldsForEmptyFieldCausesNoChange() { - BibEntry entry = new BibEntry(); - List changes = SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); - assertFalse(changes.size() > 0); - } - - @Test - public void syncSpecialFieldsFromKeywordWritesToSpecialField() { - BibEntry entry = new BibEntry(); - entry.setField(StandardField.KEYWORDS, "rank2"); - SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, ','); - assertEquals(Optional.of("rank2"), entry.getField(SpecialField.RANKING)); - } - - @Test - public void syncSpecialFieldsFromKeywordCausesChange() { - BibEntry entry = new BibEntry(); - entry.setField(StandardField.KEYWORDS, "rank2"); - List changes = SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, ','); - assertTrue(changes.size() > 0); - } - - @Test - public void syncSpecialFieldsFromKeywordCausesNoChangeWhenKeywordsAreEmpty() { - BibEntry entry = new BibEntry(); - List changes = SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, ','); - assertFalse(changes.size() > 0); - } - - @Test - public void updateFieldRemovesSpecialFieldKeywordWhenKeywordSyncIsUsed() { - BibEntry entry = new BibEntry(); - SpecialField specialField = SpecialField.PRINTED; - Keyword specialFieldKeyword = specialField.getKeyWords().get(0); - // Add the special field - SpecialFieldsUtils.updateField(specialField, specialFieldKeyword.get(), entry, true, true, ','); - // Remove it - List changes = SpecialFieldsUtils.updateField(specialField, specialFieldKeyword.get(), entry, true, true, ','); - assertEquals(Arrays.asList(new FieldChange(entry, specialField, specialFieldKeyword.get(), null), - new FieldChange(entry, StandardField.KEYWORDS, specialFieldKeyword.get(), null)), changes); - KeywordList remainingKeywords = entry.getKeywords(','); - assertFalse(remainingKeywords.contains(specialFieldKeyword)); - } -} diff --git a/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java b/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java index a5dbc4a0b10..b1f64b2ca99 100644 --- a/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java +++ b/src/test/java/org/jabref/migrations/SpecialFieldsToSeparateFieldsTest.java @@ -19,66 +19,72 @@ class SpecialFieldsToSeparateFieldsTest { @ParameterizedTest @MethodSource("provideKeywordFieldPairs") - public void migrateToCorrectField(SpecialField expectedField, String fieldInKeyword) { - BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") - .withField(StandardField.KEYWORDS, fieldInKeyword); + public void migrateToCorrectField(SpecialField field, String fieldInKeyword, BibEntry expected) { + BibEntry entry = new BibEntry().withField(StandardField.KEYWORDS, fieldInKeyword); new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); - assertEquals(fieldInKeyword, entry.getField(expectedField).get()); + assertEquals(expected, entry); } @Test public void noKewordToMigrate() { BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") .withField(StandardField.KEYWORDS, "tdd"); + BibEntry expected = new BibEntry().withField(StandardField.AUTHOR, "JabRef") + .withField(StandardField.KEYWORDS, "tdd"); + new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); - assertEquals("JabRef", entry.getField(StandardField.AUTHOR).get()); - assertEquals("tdd", entry.getField(StandardField.KEYWORDS).get()); + assertEquals(expected, entry); } @Test public void migrateMultipleSpecialFields() { BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") .withField(StandardField.KEYWORDS, "printed, prio1"); - new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); + BibEntry expected = new BibEntry().withField(StandardField.AUTHOR, "JabRef") + .withField(SpecialField.PRINTED, "printed") + .withField(SpecialField.PRIORITY, "prio1"); - assertEquals("prio1", entry.getField(SpecialField.PRIORITY).get()); - assertEquals("printed", entry.getField(SpecialField.PRINTED).get()); + new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); + assertEquals(expected, entry); } @Test public void migrateSpecialFieldsMixedWithKeyword() { BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "JabRef") .withField(StandardField.KEYWORDS, "tdd, prio1, SE"); - new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); - assertEquals("prio1", entry.getField(SpecialField.PRIORITY).get()); - assertEquals("tdd, SE", entry.getField(StandardField.KEYWORDS).get()); + BibEntry expected = new BibEntry().withField(StandardField.AUTHOR, "JabRef") + .withField(StandardField.KEYWORDS, "tdd, SE") + .withField(SpecialField.PRIORITY, "prio1"); + + new SpecialFieldsToSeparateFields(',').performMigration(new ParserResult(List.of(entry))); + assertEquals(expected, entry); } private static Stream provideKeywordFieldPairs() { return Stream.of( Arguments.of( - SpecialField.PRINTED, "printed" + SpecialField.PRINTED, "printed", new BibEntry().withField(SpecialField.PRINTED, "printed") ), Arguments.of( - SpecialField.PRIORITY, "prio1" + SpecialField.PRIORITY, "prio1", new BibEntry().withField(SpecialField.PRIORITY, "prio1") ), Arguments.of( - SpecialField.QUALITY, "qualityAssured" + SpecialField.QUALITY, "qualityAssured", new BibEntry().withField(SpecialField.QUALITY, "qualityAssured") ), Arguments.of( - SpecialField.RANKING, "rank2" + SpecialField.RANKING, "rank2", new BibEntry().withField(SpecialField.RANKING, "rank2") ), Arguments.of( - SpecialField.READ_STATUS, "skimmed" + SpecialField.READ_STATUS, "skimmed", new BibEntry().withField(SpecialField.READ_STATUS, "skimmed") ), Arguments.of( - SpecialField.RELEVANCE, "relevant" + SpecialField.RELEVANCE, "relevant", new BibEntry().withField(SpecialField.RELEVANCE, "relevant") ) ); }