From eea1b37dfe3e82e20a088be202966233d45392db Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Mon, 24 Nov 2025 01:01:38 +0530 Subject: [PATCH 01/26] Remove SmartGroup and refactor groups factory --- .../gui/collab/groupchange/GroupChange.java | 6 +-- .../gui/externalfiles/ImportHandler.java | 9 ++-- .../jabref/gui/groups/GroupDescriptions.java | 5 -- .../gui/groups/GroupDialogViewModel.java | 6 +-- .../jabref/gui/groups/GroupNodeViewModel.java | 23 +++----- .../gui/groups/GroupTreeNodeViewModel.java | 3 -- .../jabref/gui/groups/GroupTreeViewModel.java | 10 ++-- .../migrations/ConvertMarkingToGroups.java | 4 +- .../gui/groups/GroupTreeViewModelTest.java | 7 +-- .../ConvertMarkingToGroupsTest.java | 4 +- .../logic/bibtex/comparator/MetaDataDiff.java | 4 +- .../logic/exporter/GroupSerializer.java | 15 ------ .../logic/groups/DefaultGroupsFactory.java | 21 -------- .../jabref/logic/groups/GroupsFactory.java | 19 ++++++- .../importer/fileformat/BibtexParser.java | 4 +- .../logic/importer/util/GroupsParser.java | 14 +++-- .../MetadataSerializationConfiguration.java | 4 +- .../org/jabref/model/groups/SmartGroup.java | 52 ------------------- .../bibtex/comparator/MetaDataDiffTest.java | 6 +-- .../logic/exporter/GroupSerializerTest.java | 8 +-- 20 files changed, 71 insertions(+), 153 deletions(-) delete mode 100644 jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java rename jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java => jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java (61%) delete mode 100644 jablib/src/main/java/org/jabref/model/groups/SmartGroup.java diff --git a/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java b/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java index 29457b24d7a..638a0d44e58 100644 --- a/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java +++ b/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java @@ -6,7 +6,7 @@ import org.jabref.gui.groups.UndoableModifySubtree; import org.jabref.gui.undo.NamedCompoundEdit; import org.jabref.logic.bibtex.comparator.GroupDiff; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.groups.GroupTreeNode; @@ -27,7 +27,7 @@ public void applyChange(NamedCompoundEdit undoEdit) { GroupTreeNode newRoot = groupDiff.getNewGroupRoot(); GroupTreeNode root = databaseContext.getMetaData().getGroups().orElseGet(() -> { - GroupTreeNode groupTreeNode = new GroupTreeNode(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode groupTreeNode = new GroupTreeNode(GroupsFactory.getAllEntriesGroup()); databaseContext.getMetaData().setGroups(groupTreeNode); return groupTreeNode; }); @@ -38,7 +38,7 @@ public void applyChange(NamedCompoundEdit undoEdit) { root.removeAllChildren(); if (newRoot == null) { // I think setting root to null is not possible - root.setGroup(DefaultGroupsFactory.getAllEntriesGroup(), false, false, null); + root.setGroup(GroupsFactory.getAllEntriesGroup(), false, false, null); } else { // change root group, even though it'll be AllEntries anyway root.setGroup(newRoot.getGroup(), false, false, null); diff --git a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java index bce9ff7cb2b..6bf02e60a59 100644 --- a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java +++ b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java @@ -54,9 +54,9 @@ import org.jabref.model.entry.BibtexString; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupEntryChanger; import org.jabref.model.groups.GroupTreeNode; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.util.FileUpdateMonitor; import org.jabref.model.util.OptionalUtil; @@ -516,14 +516,15 @@ private List handlePdfUrl(String pdfUrl) throws IOException { private void addToImportEntriesGroup(List entriesToInsert) { if (preferences.getLibraryPreferences().isAddImportedEntriesEnabled()) { - // Only one SmartGroup + String groupName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); this.bibDatabaseContext.getMetaData() .getGroups() .flatMap(grp -> grp.getChildren() .stream() - .filter(node -> node.getGroup() instanceof SmartGroup) + .filter(node -> node.getGroup() instanceof ExplicitGroup + && node.getGroup().getName().equals(groupName)) .findFirst()) - .ifPresent(smtGrp -> smtGrp.addEntriesToGroup(entriesToInsert)); + .ifPresent(importGroup -> importGroup.addEntriesToGroup(entriesToInsert)); } } } diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java index 38499ea5ddc..2c90a222e0f 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java @@ -5,7 +5,6 @@ import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; public class GroupDescriptions { @@ -62,10 +61,6 @@ public static String getShortDescriptionAllEntriesGroup() { return Localization.lang("All Entries (this group cannot be edited or removed)"); } - public static String getShortDescriptionSmartGroup(SmartGroup smartGroup) { - return Localization.lang("Smart Group (Import Entries)"); - } - public static String getShortDescription(SearchGroup searchGroup, boolean showDynamic) { StringBuilder sb = new StringBuilder(); sb.append(""); diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java index 30eb4c07b39..a16362bf811 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java @@ -30,7 +30,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.auxparser.DefaultAuxParser; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.l10n.Localization; import org.jabref.logic.search.IndexManager; import org.jabref.logic.util.StandardFileType; @@ -416,14 +416,14 @@ public void setValues() { if (editedGroup == null) { // creating new group -> defaults! - // TODO: Create default group (via org.jabref.logic.groups.DefaultGroupsFactory) and use values + // TODO: Create default group (via org.jabref.logic.groups.GroupsFactory) and use values colorUseProperty.setValue(false); colorProperty.setValue(determineColor()); if (parentNode != null) { parentNode.getGroup() .getIconName() - .filter(iconName -> !DefaultGroupsFactory.ALL_ENTRIES_GROUP_DEFAULT_ICON.equals(iconName)) + .filter(iconName -> !GroupsFactory.ALL_ENTRIES_GROUP_DEFAULT_ICON.equals(iconName)) .ifPresent(iconProperty::setValue); parentNode.getGroup().getColor().ifPresent(color -> colorUseProperty.setValue(true)); } diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index 97eecde244e..6a63caab844 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -26,7 +26,7 @@ import org.jabref.gui.util.CustomLocalDragboard; import org.jabref.gui.util.DroppingMouseLocation; import org.jabref.gui.util.UiTaskExecutor; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; import org.jabref.logic.util.BackgroundTask; import org.jabref.logic.util.TaskExecutor; @@ -48,7 +48,6 @@ import org.jabref.model.groups.LastNameGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.search.event.IndexAddedOrUpdatedEvent; import org.jabref.model.search.event.IndexClosedEvent; @@ -141,7 +140,7 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state } static GroupNodeViewModel getAllEntriesGroup(BibDatabaseContext newDatabase, StateManager stateManager, TaskExecutor taskExecutor, CustomLocalDragboard localDragBoard, GuiPreferences preferences) { - return new GroupNodeViewModel(newDatabase, stateManager, taskExecutor, DefaultGroupsFactory.getAllEntriesGroup(), localDragBoard, preferences); + return new GroupNodeViewModel(newDatabase, stateManager, taskExecutor, GroupsFactory.getAllEntriesGroup(), localDragBoard, preferences); } private GroupNodeViewModel toViewModel(GroupTreeNode child) { @@ -437,16 +436,14 @@ public boolean hasSimilarSearchGroup(SearchGroup searchGroup) { } public boolean hasAllSuggestedGroups() { - return hasSimilarSearchGroup(JabRefSuggestedGroups.createWithoutFilesGroup()) - && hasSimilarSearchGroup(JabRefSuggestedGroups.createWithoutGroupsGroup()); + return hasSimilarSearchGroup(GroupsFactory.createWithoutFilesGroup()) + && hasSimilarSearchGroup(GroupsFactory.createWithoutGroupsGroup()); } public boolean canAddEntriesIn() { AbstractGroup group = groupNode.getGroup(); if (group instanceof AllEntriesGroup) { return false; - } else if (group instanceof SmartGroup) { - return false; } else if (group instanceof ExplicitGroup) { return true; } else if (group instanceof LastNameGroup || group instanceof RegexKeywordGroup) { @@ -477,8 +474,7 @@ public boolean canAddEntriesIn() { public boolean canBeDragged() { AbstractGroup group = groupNode.getGroup(); return switch (group) { - case AllEntriesGroup _, - SmartGroup _ -> + case AllEntriesGroup _ -> false; case ExplicitGroup _, SearchGroup _, @@ -513,8 +509,7 @@ public boolean canAddGroupsIn() { case AutomaticKeywordGroup _, AutomaticPersonsGroup _, AutomaticDateGroup _, - DateGroup _, - SmartGroup _ -> + DateGroup _ -> false; case KeywordGroup _ -> // KeywordGroup is parent of LastNameGroup, RegexKeywordGroup and WordKeywordGroup @@ -532,8 +527,7 @@ public boolean canAddGroupsIn() { public boolean canRemove() { AbstractGroup group = groupNode.getGroup(); return switch (group) { - case AllEntriesGroup _, - SmartGroup _ -> + case AllEntriesGroup _ -> false; case ExplicitGroup _, SearchGroup _, @@ -560,8 +554,7 @@ public boolean isEditable() { AbstractGroup group = groupNode.getGroup(); return switch (group) { case AllEntriesGroup _, - DateGroup _, - SmartGroup _ -> + DateGroup _ -> false; case ExplicitGroup _, SearchGroup _, diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java index d8f454931da..38f9c532988 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -17,7 +17,6 @@ import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; public class GroupTreeNodeViewModel { private final GroupTreeNode node; @@ -52,8 +51,6 @@ public String getDescription() { String shortDescription = ""; boolean showDynamic = true; shortDescription = switch (group) { - case SmartGroup smartGroup -> - GroupDescriptions.getShortDescriptionSmartGroup(smartGroup); case ExplicitGroup explicitGroup -> GroupDescriptions.getShortDescriptionExplicitGroup(explicitGroup); case KeywordGroup keywordGroup -> diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index 3048874495e..29e210c40dc 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -28,6 +28,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.CustomLocalDragboard; import org.jabref.logic.ai.AiService; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; @@ -41,7 +42,6 @@ import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; @@ -188,12 +188,12 @@ private void addGroupImportEntries(GroupNodeViewModel parent) { } String grpName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); - AbstractGroup importEntriesGroup = new SmartGroup(grpName, GroupHierarchyType.INDEPENDENT, ','); + AbstractGroup importEntriesGroup = new ExplicitGroup(grpName, GroupHierarchyType.INDEPENDENT, ','); boolean isGrpExist = parent.getGroupNode() .getChildren() .stream() .map(GroupTreeNode::getGroup) - .anyMatch(grp -> grp instanceof SmartGroup); + .anyMatch(grp -> grp instanceof ExplicitGroup && grp.getName().equals(grpName)); if (!isGrpExist) { currentDatabase.ifPresent(db -> { GroupTreeNode newSubgroup = parent.addSubgroup(importEntriesGroup); @@ -251,14 +251,14 @@ public void addSuggestedGroups(GroupNodeViewModel parent) { List newSuggestedSubgroups = new ArrayList<>(); // 1. Create "Entries without linked files" group if it doesn't exist - SearchGroup withoutFilesGroup = JabRefSuggestedGroups.createWithoutFilesGroup(); + SearchGroup withoutFilesGroup = GroupsFactory.createWithoutFilesGroup(); if (!parent.hasSimilarSearchGroup(withoutFilesGroup)) { GroupTreeNode subGroup = rootNode.addSubgroup(withoutFilesGroup); newSuggestedSubgroups.add(subGroup); } // 2. Create "Entries without groups" group if it doesn't exist - SearchGroup withoutGroupsGroup = JabRefSuggestedGroups.createWithoutGroupsGroup(); + SearchGroup withoutGroupsGroup = GroupsFactory.createWithoutGroupsGroup(); if (!parent.hasSimilarSearchGroup(withoutGroupsGroup)) { GroupTreeNode subGroup = rootNode.addSubgroup(withoutGroupsGroup); newSuggestedSubgroups.add(subGroup); diff --git a/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java b/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java index 4eb7c5611ae..924027713ba 100644 --- a/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java +++ b/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java @@ -9,7 +9,7 @@ import javafx.collections.ObservableList; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; @@ -48,7 +48,7 @@ public void performMigration(@NonNull ParserResult parserResult) { } if (parserResult.getMetaData().getGroups().isEmpty()) { - parserResult.getMetaData().setGroups(GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup())); + parserResult.getMetaData().setGroups(GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup())); } GroupTreeNode root = parserResult.getMetaData().getGroups().get(); root.addChild(markingRoot, 0); diff --git a/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java b/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java index 685cb646cca..d660a7f030d 100644 --- a/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java +++ b/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java @@ -12,6 +12,7 @@ import org.jabref.gui.util.CustomLocalDragboard; import org.jabref.logic.LibraryPreferences; import org.jabref.logic.ai.AiService; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.util.CurrentThreadTaskExecutor; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; @@ -173,7 +174,7 @@ void shouldAddsAllSuggestedGroupsWhenNoneExist() { void shouldAddOnlyMissingGroup() { GroupTreeViewModel model = new GroupTreeViewModel(stateManager, dialogService, mock(AiService.class), preferences, mock(AdaptVisibleTabs.class), taskExecutor, new CustomLocalDragboard()); GroupNodeViewModel rootGroup = model.rootGroupProperty().getValue(); - rootGroup.getGroupNode().addSubgroup(JabRefSuggestedGroups.createWithoutFilesGroup()); + rootGroup.getGroupNode().addSubgroup(GroupsFactory.createWithoutFilesGroup()); assertEquals(1, rootGroup.getChildren().size()); model.addSuggestedGroups(rootGroup); @@ -186,8 +187,8 @@ void shouldAddOnlyMissingGroup() { void shouldNotAddSuggestedGroupsWhenAllExist() { GroupTreeViewModel model = new GroupTreeViewModel(stateManager, dialogService, mock(AiService.class), preferences, mock(AdaptVisibleTabs.class), taskExecutor, new CustomLocalDragboard()); GroupNodeViewModel rootGroup = model.rootGroupProperty().getValue(); - rootGroup.getGroupNode().addSubgroup(JabRefSuggestedGroups.createWithoutFilesGroup()); - rootGroup.getGroupNode().addSubgroup(JabRefSuggestedGroups.createWithoutGroupsGroup()); + rootGroup.getGroupNode().addSubgroup(GroupsFactory.createWithoutFilesGroup()); + rootGroup.getGroupNode().addSubgroup(GroupsFactory.createWithoutGroupsGroup()); assertEquals(2, rootGroup.getChildren().size()); model.addSuggestedGroups(rootGroup); diff --git a/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java b/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java index 2ea2f07a225..e0a0ac05a2e 100644 --- a/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java +++ b/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java @@ -3,7 +3,7 @@ import java.util.Optional; import java.util.Set; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ParserResult; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.InternalField; @@ -24,7 +24,7 @@ void performMigrationForSingleEntry() { new ConvertMarkingToGroups().performMigration(parserResult); - GroupTreeNode rootExpected = GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode rootExpected = GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup()); GroupTreeNode markings = rootExpected.addSubgroup(new ExplicitGroup("Markings", GroupHierarchyType.INCLUDING, ',')); markings.addSubgroup(new ExplicitGroup("Nicolas:6", GroupHierarchyType.INCLUDING, ',')); diff --git a/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java b/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java index af1e27b9736..b122719bffa 100644 --- a/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java +++ b/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java @@ -8,7 +8,7 @@ import org.jabref.logic.citationkeypattern.CitationKeyPattern; import org.jabref.logic.citationkeypattern.GlobalCitationKeyPatterns; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.model.entry.field.Field; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.metadata.ContentSelectors; @@ -94,7 +94,7 @@ private boolean isDefaultGroup(Optional groups) { if (!groupRoot.getChildren().isEmpty()) { return false; } - return groupRoot.getGroup().equals(DefaultGroupsFactory.getAllEntriesGroup()); + return groupRoot.getGroup().equals(GroupsFactory.getAllEntriesGroup()); } /** diff --git a/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java b/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java index 0d49bb5bfa8..d62d5b23bb9 100644 --- a/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java +++ b/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java @@ -17,7 +17,6 @@ import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.search.SearchFlags; @@ -26,18 +25,6 @@ private static String serializeAllEntriesGroup() { return MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID; } - private String serializeSmartGroup(SmartGroup group) { - StringBuilder sb = new StringBuilder(); - sb.append(MetadataSerializationConfiguration.SMART_GROUP_ID); - sb.append(StringUtil.quote(group.getName(), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); - sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); - sb.append(group.getHierarchicalContext().ordinal()); - sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); - - appendGroupDetails(sb, group); - - return sb.toString(); - } private String serializeExplicitGroup(ExplicitGroup group) { StringBuilder sb = new StringBuilder(); @@ -130,8 +117,6 @@ private String serializeGroup(AbstractGroup group) { return switch (group) { case AllEntriesGroup _ -> serializeAllEntriesGroup(); - case SmartGroup smartGroup -> - serializeSmartGroup(smartGroup); case ExplicitGroup explicitGroup -> serializeExplicitGroup(explicitGroup); case KeywordGroup keywordGroup -> diff --git a/jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java b/jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java deleted file mode 100644 index d59599165cc..00000000000 --- a/jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.jabref.logic.groups; - -import org.jabref.logic.l10n.Localization; -import org.jabref.model.groups.AllEntriesGroup; - -/** - * This factory creates default groups. Currently only the allEntriesGroup is supported. - */ -public class DefaultGroupsFactory { - - public static final String ALL_ENTRIES_GROUP_DEFAULT_ICON = "ALL_ENTRIES_GROUP_ICON"; - - private DefaultGroupsFactory() { - } - - public static AllEntriesGroup getAllEntriesGroup() { - AllEntriesGroup group = new AllEntriesGroup(Localization.lang("All entries")); - group.setIconName(ALL_ENTRIES_GROUP_DEFAULT_ICON); - return group; - } -} diff --git a/jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java b/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java similarity index 61% rename from jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java rename to jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java index 644452de5db..2f3384a2f9b 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java +++ b/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java @@ -1,13 +1,28 @@ -package org.jabref.gui.groups; +package org.jabref.logic.groups; import java.util.EnumSet; import org.jabref.logic.l10n.Localization; +import org.jabref.model.groups.AllEntriesGroup; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.SearchGroup; import org.jabref.model.search.SearchFlags; -public class JabRefSuggestedGroups { +/** + * This factory creates groups. + */ +public class GroupsFactory { + + public static final String ALL_ENTRIES_GROUP_DEFAULT_ICON = "ALL_ENTRIES_GROUP_ICON"; + + private GroupsFactory() { + } + + public static AllEntriesGroup getAllEntriesGroup() { + AllEntriesGroup group = new AllEntriesGroup(Localization.lang("All entries")); + group.setIconName(ALL_ENTRIES_GROUP_DEFAULT_ICON); + return group; + } public static SearchGroup createWithoutFilesGroup() { return new SearchGroup( diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java index 5dee7354cac..cf9fb1217b1 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java @@ -28,7 +28,7 @@ import org.jabref.logic.bibtex.FieldWriter; import org.jabref.logic.exporter.BibDatabaseWriter; import org.jabref.logic.exporter.SaveConfiguration; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.Importer; import org.jabref.logic.importer.ParseException; @@ -290,7 +290,7 @@ private ParserResult parseFileContent() throws IOException { }, // metadata does not contain any groups, so we need to create an AllEntriesGroup and add the other groups as children () -> { - GroupTreeNode rootNode = new GroupTreeNode(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode rootNode = new GroupTreeNode(GroupsFactory.getAllEntriesGroup()); bibDeskGroupTreeNode.moveTo(rootNode); metaData.setGroups(rootNode); } diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index b85c391d455..047c2bb0618 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -7,7 +7,7 @@ import java.util.List; import org.jabref.logic.auxparser.DefaultAuxParser; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ParseException; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.MetadataSerializationConfiguration; @@ -27,7 +27,6 @@ import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; @@ -103,6 +102,7 @@ public static AbstractGroup fromString(String s, Character keywordSeparator, Fil return allEntriesGroupFromString(s); } if (s.startsWith(MetadataSerializationConfiguration.SMART_GROUP_ID)) { + // Migration: SmartGroup is replaced by ExplicitGroup return smartGroupFromString(s, keywordSeparator); } if (s.startsWith(MetadataSerializationConfiguration.SEARCH_GROUP_ID)) { @@ -232,7 +232,11 @@ private static KeywordGroup keywordGroupFromString(String s, Character keywordSe return newGroup; } - private static SmartGroup smartGroupFromString(String input, Character keywordSeparator) throws ParseException { + /** + * Migration method: Converts old SmartGroup serializations to ExplicitGroup. + * SmartGroup has been replaced by ExplicitGroup as they are functionally equivalent. + */ + private static ExplicitGroup smartGroupFromString(String input, Character keywordSeparator) throws ParseException { if (!input.startsWith(MetadataSerializationConfiguration.SMART_GROUP_ID)) { throw new IllegalArgumentException("SmartGroup cannot be created from \"" + input + "\"."); } @@ -242,7 +246,7 @@ private static SmartGroup smartGroupFromString(String input, Character keywordSe String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); try { int context = Integer.parseInt(tok.nextToken()); - SmartGroup newGroup = new SmartGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); + ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); addGroupDetails(tok, newGroup); return newGroup; } catch (NumberFormatException exception) { @@ -303,7 +307,7 @@ private static AbstractGroup allEntriesGroupFromString(String s) { if (!s.startsWith(MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID)) { throw new IllegalArgumentException("AllEntriesGroup cannot be created from \"" + s + "\"."); } - return DefaultGroupsFactory.getAllEntriesGroup(); + return GroupsFactory.getAllEntriesGroup(); } /** diff --git a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java index 887a6428d7f..f7d601cc2fd 100644 --- a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java +++ b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java @@ -6,7 +6,6 @@ import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; @@ -50,7 +49,8 @@ public class MetadataSerializationConfiguration { public static final String EXPLICIT_GROUP_ID = "StaticGroup:"; /** - * Identifier for {@link SmartGroup}. + * Identifier for {@link SmartGroup} (deprecated, replaced by {@link ExplicitGroup}). + * Kept for backward compatibility during migration. */ public static final String SMART_GROUP_ID = "SmartGroup:"; diff --git a/jablib/src/main/java/org/jabref/model/groups/SmartGroup.java b/jablib/src/main/java/org/jabref/model/groups/SmartGroup.java deleted file mode 100644 index e42a830f6c6..00000000000 --- a/jablib/src/main/java/org/jabref/model/groups/SmartGroup.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.jabref.model.groups; - -import java.util.Objects; - -import org.jabref.model.entry.field.StandardField; - -/** - * This group contains entries, which were automatically assigned to it. - * Assignments are stored in the {@link StandardField#GROUPS} field. - */ -public class SmartGroup extends WordKeywordGroup { - - public SmartGroup(String name, GroupHierarchyType context, Character keywordSeparator) { - super(name, context, StandardField.GROUPS, name, true, keywordSeparator, true); - } - - @Override - public AbstractGroup deepCopy() { - return new SmartGroup(getName(), getHierarchicalContext(), keywordSeparator); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if ((o == null) || (getClass() != o.getClass())) { - return false; - } - // no instanceof check as we don't want to go up the hierarchy - if (!super.equals(o)) { - return false; - } - SmartGroup other = (SmartGroup) o; - return Objects.equals(getName(), other.getName()) - && Objects.equals(getHierarchicalContext(), other.getHierarchicalContext()) - && Objects.equals(getIconName(), other.getIconName()) - && Objects.equals(getDescription(), other.getDescription()) - && Objects.equals(getColor(), other.getColor()) - && Objects.equals(isExpanded(), other.isExpanded()); - } - - @Override - public boolean isDynamic() { - return false; - } - - @Override - public int hashCode() { - return Objects.hash(name.getValue(), context, iconName, color, description, isExpanded); - } -} diff --git a/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java b/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java index 447c227f705..438ecc7229a 100644 --- a/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java +++ b/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java @@ -3,7 +3,7 @@ import java.util.List; import java.util.Optional; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.model.entry.field.StandardField; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; @@ -43,7 +43,7 @@ void defaultSettingEqualsEmptySetting() { @Test void allEntriesGroupIgnored() { MetaData one = new MetaData(); - one.setGroups(GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup())); + one.setGroups(GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup())); MetaData two = new MetaData(); assertEquals(Optional.empty(), MetaDataDiff.compare(one, two)); @@ -52,7 +52,7 @@ void allEntriesGroupIgnored() { @Test void allEntriesGroupContainingGroupNotIgnored() { MetaData one = new MetaData(); - GroupTreeNode root = GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode root = GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup()); root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING, ',')); one.setGroups(root); diff --git a/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java b/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java index e32f587e60f..f16fa871214 100644 --- a/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java +++ b/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java @@ -24,7 +24,6 @@ import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; @@ -55,10 +54,11 @@ void serializeSingleAllEntriesGroup() { } @Test - void serializeSmartGroup() { - SmartGroup group = new SmartGroup("mySmartGroup", GroupHierarchyType.INDEPENDENT, ','); + void serializeExplicitGroupReplacesSmartGroup() { + // SmartGroup has been replaced by ExplicitGroup + ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, ','); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(List.of("0 SmartGroup:mySmartGroup;0;1;;;;"), serialization); + assertEquals(List.of("0 StaticGroup:myExplicitGroup;0;1;;;;"), serialization); } @Test From 50bdad878d8a39a538de034502741eda1635eefa Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Mon, 24 Nov 2025 06:18:35 +0530 Subject: [PATCH 02/26] Removed obsolete SmartGroup localization key & Fixed KeyCollision --- .../java/org/jabref/model/database/KeyCollisionException.java | 3 +++ jablib/src/main/resources/l10n/JabRef_en.properties | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java index 05bb346599c..47bd92528f5 100644 --- a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java +++ b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java @@ -6,6 +6,7 @@ public class KeyCollisionException extends RuntimeException { public KeyCollisionException() { super(); + this.id = null; } public KeyCollisionException(String msg, String id) { @@ -15,10 +16,12 @@ public KeyCollisionException(String msg, String id) { public KeyCollisionException(String msg, Throwable exception) { super(msg, exception); + this.id = null; } public KeyCollisionException(Throwable exception) { super(exception); + this.id = null; } public String getId() { diff --git a/jablib/src/main/resources/l10n/JabRef_en.properties b/jablib/src/main/resources/l10n/JabRef_en.properties index e9126cce139..f9ed7ce5c51 100644 --- a/jablib/src/main/resources/l10n/JabRef_en.properties +++ b/jablib/src/main/resources/l10n/JabRef_en.properties @@ -2515,7 +2515,6 @@ Unprotect\ terms=Unprotect terms Generate\ a\ new\ key\ for\ imported\ entries\ (overwriting\ their\ default)=Generate a new key for imported entries (overwriting their default) Warn\ about\ duplicates\ on\ import=Warn about duplicates on import Add\ imported\ entries\ to\ group=Add imported entries to group -Smart\ Group\ (Import\ Entries)=Smart Group (Import Entries) Imported\ entries=Imported entries Custom\ DOI\ URI=Custom DOI URI From 5aaadc6c041af21216a6a0b28068042ca43f765b Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Mon, 24 Nov 2025 15:49:06 +0530 Subject: [PATCH 03/26] Fix the code so the @NonNull field id in KeyCollisionException.java is initialized in every constructor. --- .../model/database/KeyCollisionException.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java index 47bd92528f5..354cabffe12 100644 --- a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java +++ b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java @@ -1,30 +1,36 @@ package org.jabref.model.database; +import java.util.Objects; + +import org.jspecify.annotations.NonNull; + public class KeyCollisionException extends RuntimeException { - private String id; + private static final String UNKNOWN_ID = ""; + + private final @NonNull String id; public KeyCollisionException() { super(); - this.id = null; + this.id = UNKNOWN_ID; } public KeyCollisionException(String msg, String id) { super(msg); - this.id = id; + this.id = Objects.requireNonNullElse(id, UNKNOWN_ID); } public KeyCollisionException(String msg, Throwable exception) { super(msg, exception); - this.id = null; + this.id = UNKNOWN_ID; } public KeyCollisionException(Throwable exception) { super(exception); - this.id = null; + this.id = UNKNOWN_ID; } - public String getId() { + public @NonNull String getId() { return id; } } From 5b257a0297870424128de6a179ce68818b69c12d Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 02:57:23 +0530 Subject: [PATCH 04/26] added a test for the migraiton of the SmartGroup to the new Explicit groups and added tests for parsing and roundtrip --- .../logic/importer/util/GroupsParserTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index 76572f39cdc..48475585db0 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -9,6 +9,7 @@ import javafx.scene.paint.Color; import org.jabref.logic.auxparser.DefaultAuxParser; +import org.jabref.logic.exporter.GroupSerializer; import org.jabref.logic.importer.ParseException; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.field.StandardField; @@ -174,4 +175,27 @@ void fromStringParsesAutomaticDateGroupWithColorAndIcon() throws ParseException AbstractGroup parsed = GroupsParser.fromString("AutomaticDateGroup:Publications;0;year;YEAR;1;0x0000ffff;calendar;Group by publication year;", ',', fileMonitor, metaData, "userAndHost"); assertEquals(expected, parsed); } + + @Test + void fromStringParsesSmartGroupAsExplicitGroup() throws ParseException { + ExplicitGroup expected = new ExplicitGroup("legacySmart", GroupHierarchyType.INDEPENDENT, ','); + expected.setExpanded(true); + expected.setColor(Color.AQUA.toString()); + expected.setIconName("smart-icon"); + expected.setDescription("legacy description"); + + AbstractGroup parsed = GroupsParser.fromString("SmartGroup:legacySmart;0;1;0x00ffffff;smart-icon;legacy description;", ',', fileMonitor, metaData, "userAndHost"); + + assertEquals(expected, parsed); + } + + @Test + void smartGroupRoundtripResultsInExplicitSerialization() throws ParseException { + AbstractGroup parsed = GroupsParser.fromString("SmartGroup:roundtrip;2;0;0x00ff00ff;icon;desc;", ',', fileMonitor, metaData, "userAndHost"); + + GroupSerializer serializer = new GroupSerializer(); + List serialization = serializer.serializeTree(GroupTreeNode.fromGroup(parsed)); + + assertEquals(List.of("0 StaticGroup:roundtrip;2;0;0x00ff00ff;icon;desc;"), serialization); + } } From 84d7c988b2b581aa9e3f6d7affee3ef0a781fdd3 Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Mon, 24 Nov 2025 01:01:38 +0530 Subject: [PATCH 05/26] Remove SmartGroup and refactor groups factory # Conflicts: # jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java --- .../gui/collab/groupchange/GroupChange.java | 6 +-- .../jabref/gui/groups/GroupDescriptions.java | 5 -- .../gui/groups/GroupDialogViewModel.java | 6 +-- .../jabref/gui/groups/GroupNodeViewModel.java | 23 +++----- .../gui/groups/GroupTreeNodeViewModel.java | 3 -- .../jabref/gui/groups/GroupTreeViewModel.java | 10 ++-- .../migrations/ConvertMarkingToGroups.java | 4 +- .../gui/groups/GroupTreeViewModelTest.java | 7 +-- .../ConvertMarkingToGroupsTest.java | 4 +- .../logic/bibtex/comparator/MetaDataDiff.java | 4 +- .../logic/exporter/GroupSerializer.java | 15 ------ .../logic/groups/DefaultGroupsFactory.java | 21 -------- .../jabref/logic/groups/GroupsFactory.java | 19 ++++++- .../importer/fileformat/BibtexParser.java | 4 +- .../logic/importer/util/GroupsParser.java | 14 +++-- .../MetadataSerializationConfiguration.java | 4 +- .../org/jabref/model/groups/SmartGroup.java | 52 ------------------- .../bibtex/comparator/MetaDataDiffTest.java | 6 +-- .../logic/exporter/GroupSerializerTest.java | 8 +-- 19 files changed, 66 insertions(+), 149 deletions(-) delete mode 100644 jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java rename jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java => jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java (61%) delete mode 100644 jablib/src/main/java/org/jabref/model/groups/SmartGroup.java diff --git a/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java b/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java index 29457b24d7a..638a0d44e58 100644 --- a/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java +++ b/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java @@ -6,7 +6,7 @@ import org.jabref.gui.groups.UndoableModifySubtree; import org.jabref.gui.undo.NamedCompoundEdit; import org.jabref.logic.bibtex.comparator.GroupDiff; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.groups.GroupTreeNode; @@ -27,7 +27,7 @@ public void applyChange(NamedCompoundEdit undoEdit) { GroupTreeNode newRoot = groupDiff.getNewGroupRoot(); GroupTreeNode root = databaseContext.getMetaData().getGroups().orElseGet(() -> { - GroupTreeNode groupTreeNode = new GroupTreeNode(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode groupTreeNode = new GroupTreeNode(GroupsFactory.getAllEntriesGroup()); databaseContext.getMetaData().setGroups(groupTreeNode); return groupTreeNode; }); @@ -38,7 +38,7 @@ public void applyChange(NamedCompoundEdit undoEdit) { root.removeAllChildren(); if (newRoot == null) { // I think setting root to null is not possible - root.setGroup(DefaultGroupsFactory.getAllEntriesGroup(), false, false, null); + root.setGroup(GroupsFactory.getAllEntriesGroup(), false, false, null); } else { // change root group, even though it'll be AllEntries anyway root.setGroup(newRoot.getGroup(), false, false, null); diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java index 38499ea5ddc..2c90a222e0f 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupDescriptions.java @@ -5,7 +5,6 @@ import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; public class GroupDescriptions { @@ -62,10 +61,6 @@ public static String getShortDescriptionAllEntriesGroup() { return Localization.lang("All Entries (this group cannot be edited or removed)"); } - public static String getShortDescriptionSmartGroup(SmartGroup smartGroup) { - return Localization.lang("Smart Group (Import Entries)"); - } - public static String getShortDescription(SearchGroup searchGroup, boolean showDynamic) { StringBuilder sb = new StringBuilder(); sb.append(""); diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java index 30eb4c07b39..a16362bf811 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java @@ -30,7 +30,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.auxparser.DefaultAuxParser; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.l10n.Localization; import org.jabref.logic.search.IndexManager; import org.jabref.logic.util.StandardFileType; @@ -416,14 +416,14 @@ public void setValues() { if (editedGroup == null) { // creating new group -> defaults! - // TODO: Create default group (via org.jabref.logic.groups.DefaultGroupsFactory) and use values + // TODO: Create default group (via org.jabref.logic.groups.GroupsFactory) and use values colorUseProperty.setValue(false); colorProperty.setValue(determineColor()); if (parentNode != null) { parentNode.getGroup() .getIconName() - .filter(iconName -> !DefaultGroupsFactory.ALL_ENTRIES_GROUP_DEFAULT_ICON.equals(iconName)) + .filter(iconName -> !GroupsFactory.ALL_ENTRIES_GROUP_DEFAULT_ICON.equals(iconName)) .ifPresent(iconProperty::setValue); parentNode.getGroup().getColor().ifPresent(color -> colorUseProperty.setValue(true)); } diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index 97eecde244e..6a63caab844 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -26,7 +26,7 @@ import org.jabref.gui.util.CustomLocalDragboard; import org.jabref.gui.util.DroppingMouseLocation; import org.jabref.gui.util.UiTaskExecutor; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; import org.jabref.logic.util.BackgroundTask; import org.jabref.logic.util.TaskExecutor; @@ -48,7 +48,6 @@ import org.jabref.model.groups.LastNameGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.search.event.IndexAddedOrUpdatedEvent; import org.jabref.model.search.event.IndexClosedEvent; @@ -141,7 +140,7 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state } static GroupNodeViewModel getAllEntriesGroup(BibDatabaseContext newDatabase, StateManager stateManager, TaskExecutor taskExecutor, CustomLocalDragboard localDragBoard, GuiPreferences preferences) { - return new GroupNodeViewModel(newDatabase, stateManager, taskExecutor, DefaultGroupsFactory.getAllEntriesGroup(), localDragBoard, preferences); + return new GroupNodeViewModel(newDatabase, stateManager, taskExecutor, GroupsFactory.getAllEntriesGroup(), localDragBoard, preferences); } private GroupNodeViewModel toViewModel(GroupTreeNode child) { @@ -437,16 +436,14 @@ public boolean hasSimilarSearchGroup(SearchGroup searchGroup) { } public boolean hasAllSuggestedGroups() { - return hasSimilarSearchGroup(JabRefSuggestedGroups.createWithoutFilesGroup()) - && hasSimilarSearchGroup(JabRefSuggestedGroups.createWithoutGroupsGroup()); + return hasSimilarSearchGroup(GroupsFactory.createWithoutFilesGroup()) + && hasSimilarSearchGroup(GroupsFactory.createWithoutGroupsGroup()); } public boolean canAddEntriesIn() { AbstractGroup group = groupNode.getGroup(); if (group instanceof AllEntriesGroup) { return false; - } else if (group instanceof SmartGroup) { - return false; } else if (group instanceof ExplicitGroup) { return true; } else if (group instanceof LastNameGroup || group instanceof RegexKeywordGroup) { @@ -477,8 +474,7 @@ public boolean canAddEntriesIn() { public boolean canBeDragged() { AbstractGroup group = groupNode.getGroup(); return switch (group) { - case AllEntriesGroup _, - SmartGroup _ -> + case AllEntriesGroup _ -> false; case ExplicitGroup _, SearchGroup _, @@ -513,8 +509,7 @@ public boolean canAddGroupsIn() { case AutomaticKeywordGroup _, AutomaticPersonsGroup _, AutomaticDateGroup _, - DateGroup _, - SmartGroup _ -> + DateGroup _ -> false; case KeywordGroup _ -> // KeywordGroup is parent of LastNameGroup, RegexKeywordGroup and WordKeywordGroup @@ -532,8 +527,7 @@ public boolean canAddGroupsIn() { public boolean canRemove() { AbstractGroup group = groupNode.getGroup(); return switch (group) { - case AllEntriesGroup _, - SmartGroup _ -> + case AllEntriesGroup _ -> false; case ExplicitGroup _, SearchGroup _, @@ -560,8 +554,7 @@ public boolean isEditable() { AbstractGroup group = groupNode.getGroup(); return switch (group) { case AllEntriesGroup _, - DateGroup _, - SmartGroup _ -> + DateGroup _ -> false; case ExplicitGroup _, SearchGroup _, diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java index d8f454931da..38f9c532988 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -17,7 +17,6 @@ import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; public class GroupTreeNodeViewModel { private final GroupTreeNode node; @@ -52,8 +51,6 @@ public String getDescription() { String shortDescription = ""; boolean showDynamic = true; shortDescription = switch (group) { - case SmartGroup smartGroup -> - GroupDescriptions.getShortDescriptionSmartGroup(smartGroup); case ExplicitGroup explicitGroup -> GroupDescriptions.getShortDescriptionExplicitGroup(explicitGroup); case KeywordGroup keywordGroup -> diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index 3048874495e..29e210c40dc 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -28,6 +28,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.CustomLocalDragboard; import org.jabref.logic.ai.AiService; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; @@ -41,7 +42,6 @@ import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; @@ -188,12 +188,12 @@ private void addGroupImportEntries(GroupNodeViewModel parent) { } String grpName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); - AbstractGroup importEntriesGroup = new SmartGroup(grpName, GroupHierarchyType.INDEPENDENT, ','); + AbstractGroup importEntriesGroup = new ExplicitGroup(grpName, GroupHierarchyType.INDEPENDENT, ','); boolean isGrpExist = parent.getGroupNode() .getChildren() .stream() .map(GroupTreeNode::getGroup) - .anyMatch(grp -> grp instanceof SmartGroup); + .anyMatch(grp -> grp instanceof ExplicitGroup && grp.getName().equals(grpName)); if (!isGrpExist) { currentDatabase.ifPresent(db -> { GroupTreeNode newSubgroup = parent.addSubgroup(importEntriesGroup); @@ -251,14 +251,14 @@ public void addSuggestedGroups(GroupNodeViewModel parent) { List newSuggestedSubgroups = new ArrayList<>(); // 1. Create "Entries without linked files" group if it doesn't exist - SearchGroup withoutFilesGroup = JabRefSuggestedGroups.createWithoutFilesGroup(); + SearchGroup withoutFilesGroup = GroupsFactory.createWithoutFilesGroup(); if (!parent.hasSimilarSearchGroup(withoutFilesGroup)) { GroupTreeNode subGroup = rootNode.addSubgroup(withoutFilesGroup); newSuggestedSubgroups.add(subGroup); } // 2. Create "Entries without groups" group if it doesn't exist - SearchGroup withoutGroupsGroup = JabRefSuggestedGroups.createWithoutGroupsGroup(); + SearchGroup withoutGroupsGroup = GroupsFactory.createWithoutGroupsGroup(); if (!parent.hasSimilarSearchGroup(withoutGroupsGroup)) { GroupTreeNode subGroup = rootNode.addSubgroup(withoutGroupsGroup); newSuggestedSubgroups.add(subGroup); diff --git a/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java b/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java index 4eb7c5611ae..924027713ba 100644 --- a/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java +++ b/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java @@ -9,7 +9,7 @@ import javafx.collections.ObservableList; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; @@ -48,7 +48,7 @@ public void performMigration(@NonNull ParserResult parserResult) { } if (parserResult.getMetaData().getGroups().isEmpty()) { - parserResult.getMetaData().setGroups(GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup())); + parserResult.getMetaData().setGroups(GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup())); } GroupTreeNode root = parserResult.getMetaData().getGroups().get(); root.addChild(markingRoot, 0); diff --git a/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java b/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java index 685cb646cca..d660a7f030d 100644 --- a/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java +++ b/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java @@ -12,6 +12,7 @@ import org.jabref.gui.util.CustomLocalDragboard; import org.jabref.logic.LibraryPreferences; import org.jabref.logic.ai.AiService; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.util.CurrentThreadTaskExecutor; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; @@ -173,7 +174,7 @@ void shouldAddsAllSuggestedGroupsWhenNoneExist() { void shouldAddOnlyMissingGroup() { GroupTreeViewModel model = new GroupTreeViewModel(stateManager, dialogService, mock(AiService.class), preferences, mock(AdaptVisibleTabs.class), taskExecutor, new CustomLocalDragboard()); GroupNodeViewModel rootGroup = model.rootGroupProperty().getValue(); - rootGroup.getGroupNode().addSubgroup(JabRefSuggestedGroups.createWithoutFilesGroup()); + rootGroup.getGroupNode().addSubgroup(GroupsFactory.createWithoutFilesGroup()); assertEquals(1, rootGroup.getChildren().size()); model.addSuggestedGroups(rootGroup); @@ -186,8 +187,8 @@ void shouldAddOnlyMissingGroup() { void shouldNotAddSuggestedGroupsWhenAllExist() { GroupTreeViewModel model = new GroupTreeViewModel(stateManager, dialogService, mock(AiService.class), preferences, mock(AdaptVisibleTabs.class), taskExecutor, new CustomLocalDragboard()); GroupNodeViewModel rootGroup = model.rootGroupProperty().getValue(); - rootGroup.getGroupNode().addSubgroup(JabRefSuggestedGroups.createWithoutFilesGroup()); - rootGroup.getGroupNode().addSubgroup(JabRefSuggestedGroups.createWithoutGroupsGroup()); + rootGroup.getGroupNode().addSubgroup(GroupsFactory.createWithoutFilesGroup()); + rootGroup.getGroupNode().addSubgroup(GroupsFactory.createWithoutGroupsGroup()); assertEquals(2, rootGroup.getChildren().size()); model.addSuggestedGroups(rootGroup); diff --git a/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java b/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java index 2ea2f07a225..e0a0ac05a2e 100644 --- a/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java +++ b/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java @@ -3,7 +3,7 @@ import java.util.Optional; import java.util.Set; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ParserResult; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.InternalField; @@ -24,7 +24,7 @@ void performMigrationForSingleEntry() { new ConvertMarkingToGroups().performMigration(parserResult); - GroupTreeNode rootExpected = GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode rootExpected = GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup()); GroupTreeNode markings = rootExpected.addSubgroup(new ExplicitGroup("Markings", GroupHierarchyType.INCLUDING, ',')); markings.addSubgroup(new ExplicitGroup("Nicolas:6", GroupHierarchyType.INCLUDING, ',')); diff --git a/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java b/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java index af1e27b9736..b122719bffa 100644 --- a/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java +++ b/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java @@ -8,7 +8,7 @@ import org.jabref.logic.citationkeypattern.CitationKeyPattern; import org.jabref.logic.citationkeypattern.GlobalCitationKeyPatterns; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.model.entry.field.Field; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.metadata.ContentSelectors; @@ -94,7 +94,7 @@ private boolean isDefaultGroup(Optional groups) { if (!groupRoot.getChildren().isEmpty()) { return false; } - return groupRoot.getGroup().equals(DefaultGroupsFactory.getAllEntriesGroup()); + return groupRoot.getGroup().equals(GroupsFactory.getAllEntriesGroup()); } /** diff --git a/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java b/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java index 0d49bb5bfa8..d62d5b23bb9 100644 --- a/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java +++ b/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java @@ -17,7 +17,6 @@ import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.search.SearchFlags; @@ -26,18 +25,6 @@ private static String serializeAllEntriesGroup() { return MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID; } - private String serializeSmartGroup(SmartGroup group) { - StringBuilder sb = new StringBuilder(); - sb.append(MetadataSerializationConfiguration.SMART_GROUP_ID); - sb.append(StringUtil.quote(group.getName(), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); - sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); - sb.append(group.getHierarchicalContext().ordinal()); - sb.append(MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR); - - appendGroupDetails(sb, group); - - return sb.toString(); - } private String serializeExplicitGroup(ExplicitGroup group) { StringBuilder sb = new StringBuilder(); @@ -130,8 +117,6 @@ private String serializeGroup(AbstractGroup group) { return switch (group) { case AllEntriesGroup _ -> serializeAllEntriesGroup(); - case SmartGroup smartGroup -> - serializeSmartGroup(smartGroup); case ExplicitGroup explicitGroup -> serializeExplicitGroup(explicitGroup); case KeywordGroup keywordGroup -> diff --git a/jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java b/jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java deleted file mode 100644 index d59599165cc..00000000000 --- a/jablib/src/main/java/org/jabref/logic/groups/DefaultGroupsFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.jabref.logic.groups; - -import org.jabref.logic.l10n.Localization; -import org.jabref.model.groups.AllEntriesGroup; - -/** - * This factory creates default groups. Currently only the allEntriesGroup is supported. - */ -public class DefaultGroupsFactory { - - public static final String ALL_ENTRIES_GROUP_DEFAULT_ICON = "ALL_ENTRIES_GROUP_ICON"; - - private DefaultGroupsFactory() { - } - - public static AllEntriesGroup getAllEntriesGroup() { - AllEntriesGroup group = new AllEntriesGroup(Localization.lang("All entries")); - group.setIconName(ALL_ENTRIES_GROUP_DEFAULT_ICON); - return group; - } -} diff --git a/jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java b/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java similarity index 61% rename from jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java rename to jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java index 644452de5db..2f3384a2f9b 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/JabRefSuggestedGroups.java +++ b/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java @@ -1,13 +1,28 @@ -package org.jabref.gui.groups; +package org.jabref.logic.groups; import java.util.EnumSet; import org.jabref.logic.l10n.Localization; +import org.jabref.model.groups.AllEntriesGroup; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.SearchGroup; import org.jabref.model.search.SearchFlags; -public class JabRefSuggestedGroups { +/** + * This factory creates groups. + */ +public class GroupsFactory { + + public static final String ALL_ENTRIES_GROUP_DEFAULT_ICON = "ALL_ENTRIES_GROUP_ICON"; + + private GroupsFactory() { + } + + public static AllEntriesGroup getAllEntriesGroup() { + AllEntriesGroup group = new AllEntriesGroup(Localization.lang("All entries")); + group.setIconName(ALL_ENTRIES_GROUP_DEFAULT_ICON); + return group; + } public static SearchGroup createWithoutFilesGroup() { return new SearchGroup( diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java index 5dee7354cac..cf9fb1217b1 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java @@ -28,7 +28,7 @@ import org.jabref.logic.bibtex.FieldWriter; import org.jabref.logic.exporter.BibDatabaseWriter; import org.jabref.logic.exporter.SaveConfiguration; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.Importer; import org.jabref.logic.importer.ParseException; @@ -290,7 +290,7 @@ private ParserResult parseFileContent() throws IOException { }, // metadata does not contain any groups, so we need to create an AllEntriesGroup and add the other groups as children () -> { - GroupTreeNode rootNode = new GroupTreeNode(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode rootNode = new GroupTreeNode(GroupsFactory.getAllEntriesGroup()); bibDeskGroupTreeNode.moveTo(rootNode); metaData.setGroups(rootNode); } diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index b85c391d455..047c2bb0618 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -7,7 +7,7 @@ import java.util.List; import org.jabref.logic.auxparser.DefaultAuxParser; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.logic.importer.ParseException; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.MetadataSerializationConfiguration; @@ -27,7 +27,6 @@ import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; @@ -103,6 +102,7 @@ public static AbstractGroup fromString(String s, Character keywordSeparator, Fil return allEntriesGroupFromString(s); } if (s.startsWith(MetadataSerializationConfiguration.SMART_GROUP_ID)) { + // Migration: SmartGroup is replaced by ExplicitGroup return smartGroupFromString(s, keywordSeparator); } if (s.startsWith(MetadataSerializationConfiguration.SEARCH_GROUP_ID)) { @@ -232,7 +232,11 @@ private static KeywordGroup keywordGroupFromString(String s, Character keywordSe return newGroup; } - private static SmartGroup smartGroupFromString(String input, Character keywordSeparator) throws ParseException { + /** + * Migration method: Converts old SmartGroup serializations to ExplicitGroup. + * SmartGroup has been replaced by ExplicitGroup as they are functionally equivalent. + */ + private static ExplicitGroup smartGroupFromString(String input, Character keywordSeparator) throws ParseException { if (!input.startsWith(MetadataSerializationConfiguration.SMART_GROUP_ID)) { throw new IllegalArgumentException("SmartGroup cannot be created from \"" + input + "\"."); } @@ -242,7 +246,7 @@ private static SmartGroup smartGroupFromString(String input, Character keywordSe String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); try { int context = Integer.parseInt(tok.nextToken()); - SmartGroup newGroup = new SmartGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); + ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); addGroupDetails(tok, newGroup); return newGroup; } catch (NumberFormatException exception) { @@ -303,7 +307,7 @@ private static AbstractGroup allEntriesGroupFromString(String s) { if (!s.startsWith(MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID)) { throw new IllegalArgumentException("AllEntriesGroup cannot be created from \"" + s + "\"."); } - return DefaultGroupsFactory.getAllEntriesGroup(); + return GroupsFactory.getAllEntriesGroup(); } /** diff --git a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java index 887a6428d7f..f7d601cc2fd 100644 --- a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java +++ b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java @@ -6,7 +6,6 @@ import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; @@ -50,7 +49,8 @@ public class MetadataSerializationConfiguration { public static final String EXPLICIT_GROUP_ID = "StaticGroup:"; /** - * Identifier for {@link SmartGroup}. + * Identifier for {@link SmartGroup} (deprecated, replaced by {@link ExplicitGroup}). + * Kept for backward compatibility during migration. */ public static final String SMART_GROUP_ID = "SmartGroup:"; diff --git a/jablib/src/main/java/org/jabref/model/groups/SmartGroup.java b/jablib/src/main/java/org/jabref/model/groups/SmartGroup.java deleted file mode 100644 index e42a830f6c6..00000000000 --- a/jablib/src/main/java/org/jabref/model/groups/SmartGroup.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.jabref.model.groups; - -import java.util.Objects; - -import org.jabref.model.entry.field.StandardField; - -/** - * This group contains entries, which were automatically assigned to it. - * Assignments are stored in the {@link StandardField#GROUPS} field. - */ -public class SmartGroup extends WordKeywordGroup { - - public SmartGroup(String name, GroupHierarchyType context, Character keywordSeparator) { - super(name, context, StandardField.GROUPS, name, true, keywordSeparator, true); - } - - @Override - public AbstractGroup deepCopy() { - return new SmartGroup(getName(), getHierarchicalContext(), keywordSeparator); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if ((o == null) || (getClass() != o.getClass())) { - return false; - } - // no instanceof check as we don't want to go up the hierarchy - if (!super.equals(o)) { - return false; - } - SmartGroup other = (SmartGroup) o; - return Objects.equals(getName(), other.getName()) - && Objects.equals(getHierarchicalContext(), other.getHierarchicalContext()) - && Objects.equals(getIconName(), other.getIconName()) - && Objects.equals(getDescription(), other.getDescription()) - && Objects.equals(getColor(), other.getColor()) - && Objects.equals(isExpanded(), other.isExpanded()); - } - - @Override - public boolean isDynamic() { - return false; - } - - @Override - public int hashCode() { - return Objects.hash(name.getValue(), context, iconName, color, description, isExpanded); - } -} diff --git a/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java b/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java index 447c227f705..438ecc7229a 100644 --- a/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java +++ b/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java @@ -3,7 +3,7 @@ import java.util.List; import java.util.Optional; -import org.jabref.logic.groups.DefaultGroupsFactory; +import org.jabref.logic.groups.GroupsFactory; import org.jabref.model.entry.field.StandardField; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; @@ -43,7 +43,7 @@ void defaultSettingEqualsEmptySetting() { @Test void allEntriesGroupIgnored() { MetaData one = new MetaData(); - one.setGroups(GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup())); + one.setGroups(GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup())); MetaData two = new MetaData(); assertEquals(Optional.empty(), MetaDataDiff.compare(one, two)); @@ -52,7 +52,7 @@ void allEntriesGroupIgnored() { @Test void allEntriesGroupContainingGroupNotIgnored() { MetaData one = new MetaData(); - GroupTreeNode root = GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup()); + GroupTreeNode root = GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup()); root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING, ',')); one.setGroups(root); diff --git a/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java b/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java index e32f587e60f..f16fa871214 100644 --- a/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java +++ b/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java @@ -24,7 +24,6 @@ import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.model.groups.SmartGroup; import org.jabref.model.groups.TexGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; @@ -55,10 +54,11 @@ void serializeSingleAllEntriesGroup() { } @Test - void serializeSmartGroup() { - SmartGroup group = new SmartGroup("mySmartGroup", GroupHierarchyType.INDEPENDENT, ','); + void serializeExplicitGroupReplacesSmartGroup() { + // SmartGroup has been replaced by ExplicitGroup + ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, ','); List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(List.of("0 SmartGroup:mySmartGroup;0;1;;;;"), serialization); + assertEquals(List.of("0 StaticGroup:myExplicitGroup;0;1;;;;"), serialization); } @Test From d8a2d4379a5de3292e067b2049bbd8e15dd145f8 Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Mon, 24 Nov 2025 06:18:35 +0530 Subject: [PATCH 06/26] Removed obsolete SmartGroup localization key & Fixed KeyCollision --- .../java/org/jabref/model/database/KeyCollisionException.java | 3 +++ jablib/src/main/resources/l10n/JabRef_en.properties | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java index 05bb346599c..47bd92528f5 100644 --- a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java +++ b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java @@ -6,6 +6,7 @@ public class KeyCollisionException extends RuntimeException { public KeyCollisionException() { super(); + this.id = null; } public KeyCollisionException(String msg, String id) { @@ -15,10 +16,12 @@ public KeyCollisionException(String msg, String id) { public KeyCollisionException(String msg, Throwable exception) { super(msg, exception); + this.id = null; } public KeyCollisionException(Throwable exception) { super(exception); + this.id = null; } public String getId() { diff --git a/jablib/src/main/resources/l10n/JabRef_en.properties b/jablib/src/main/resources/l10n/JabRef_en.properties index 064e16b9b96..4cf1c70b1ed 100644 --- a/jablib/src/main/resources/l10n/JabRef_en.properties +++ b/jablib/src/main/resources/l10n/JabRef_en.properties @@ -2530,7 +2530,6 @@ Unprotect\ terms=Unprotect terms Generate\ a\ new\ key\ for\ imported\ entries\ (overwriting\ their\ default)=Generate a new key for imported entries (overwriting their default) Warn\ about\ duplicates\ on\ import=Warn about duplicates on import Add\ imported\ entries\ to\ group=Add imported entries to group -Smart\ Group\ (Import\ Entries)=Smart Group (Import Entries) Imported\ entries=Imported entries Custom\ DOI\ URI=Custom DOI URI From 12bff581cd97c17eaa9eccfbbd3c83fa7546a35a Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Mon, 24 Nov 2025 15:49:06 +0530 Subject: [PATCH 07/26] Fix the code so the @NonNull field id in KeyCollisionException.java is initialized in every constructor. --- .../model/database/KeyCollisionException.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java index 47bd92528f5..354cabffe12 100644 --- a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java +++ b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java @@ -1,30 +1,36 @@ package org.jabref.model.database; +import java.util.Objects; + +import org.jspecify.annotations.NonNull; + public class KeyCollisionException extends RuntimeException { - private String id; + private static final String UNKNOWN_ID = ""; + + private final @NonNull String id; public KeyCollisionException() { super(); - this.id = null; + this.id = UNKNOWN_ID; } public KeyCollisionException(String msg, String id) { super(msg); - this.id = id; + this.id = Objects.requireNonNullElse(id, UNKNOWN_ID); } public KeyCollisionException(String msg, Throwable exception) { super(msg, exception); - this.id = null; + this.id = UNKNOWN_ID; } public KeyCollisionException(Throwable exception) { super(exception); - this.id = null; + this.id = UNKNOWN_ID; } - public String getId() { + public @NonNull String getId() { return id; } } From 67830d7216b14f49110dca3c793d10b00810b5f5 Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 04:16:52 +0530 Subject: [PATCH 08/26] added a test for the migration of the SmartGroup to the new Explicit groups and ideally roundtrip test. --- .../logic/importer/util/GroupsParserTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index 76572f39cdc..7e91a479bd0 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -33,6 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; class GroupsParserTest { private FileUpdateMonitor fileMonitor; @@ -174,4 +175,36 @@ void fromStringParsesAutomaticDateGroupWithColorAndIcon() throws ParseException AbstractGroup parsed = GroupsParser.fromString("AutomaticDateGroup:Publications;0;year;YEAR;1;0x0000ffff;calendar;Group by publication year;", ',', fileMonitor, metaData, "userAndHost"); assertEquals(expected, parsed); } + + @Test + void fromStringParsesSmartGroupAndMigratesToExplicitGroup() throws ParseException { + ExplicitGroup expected = new ExplicitGroup("MySmartGroup", GroupHierarchyType.INDEPENDENT, ','); + AbstractGroup parsed = GroupsParser.fromString("SmartGroup:MySmartGroup;0;", ',', fileMonitor, metaData, "userAndHost"); + + assertEquals(ExplicitGroup.class, parsed.getClass()); + assertEquals(expected, parsed); + } + + @Test + void roundtripSmartGroupToExplicitGroup() throws ParseException { + // Read old SmartGroup format + String smartGroupString = "SmartGroup:MyGroup;0;1;0xf0f8ffff;icon-name;Group description;"; + AbstractGroup parsed = GroupsParser.fromString(smartGroupString, ',', fileMonitor, metaData, "userAndHost"); + assertEquals(ExplicitGroup.class, parsed.getClass()); + + // Store in new format (serialize) + org.jabref.logic.exporter.GroupSerializer serializer = new org.jabref.logic.exporter.GroupSerializer(); + List serialized = serializer.serializeTree(GroupTreeNode.fromGroup(parsed)); + String serializedString = serialized.get(0).substring(2); // Remove level prefix "0 " + + // Verify it's stored as StaticGroup (ExplicitGroup format), not SmartGroup + assertTrue(serializedString.startsWith("StaticGroup:")); + + // Read the new format + AbstractGroup roundtripParsed = GroupsParser.fromString(serializedString, ',', fileMonitor, metaData, "userAndHost"); + + // Verify it's still ExplicitGroup and properties are preserved + assertEquals(ExplicitGroup.class, roundtripParsed.getClass()); + assertEquals(parsed, roundtripParsed); + } } From 00a54f8e18bd0e7b7d156f23b62ad729424cc74d Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 04:49:44 +0530 Subject: [PATCH 09/26] fixed format errors --- .../main/java/org/jabref/gui/externalfiles/ImportHandler.java | 2 +- .../main/java/org/jabref/logic/exporter/GroupSerializer.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java index e2b8ed02dd2..f5f1a983b5c 100644 --- a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java +++ b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java @@ -534,7 +534,7 @@ private List handlePdfUrl(String pdfUrl) throws IOException { private void addToImportEntriesGroup(List entriesToInsert) { if (preferences.getLibraryPreferences().isAddImportedEntriesEnabled()) { String groupName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); - this.bibDatabaseContext.getMetaData() + this.targetBibDatabaseContext.getMetaData() .getGroups() .flatMap(grp -> grp.getChildren() .stream() diff --git a/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java b/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java index d62d5b23bb9..272d5e20257 100644 --- a/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java +++ b/jablib/src/main/java/org/jabref/logic/exporter/GroupSerializer.java @@ -25,7 +25,6 @@ private static String serializeAllEntriesGroup() { return MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID; } - private String serializeExplicitGroup(ExplicitGroup group) { StringBuilder sb = new StringBuilder(); sb.append(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID); From d2141eb0522d16a6e8d87968496455026417e35b Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 04:54:29 +0530 Subject: [PATCH 10/26] fixed format --- .../jabref/gui/externalfiles/ImportHandler.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java index f5f1a983b5c..596c6f1b0b4 100644 --- a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java +++ b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java @@ -535,13 +535,13 @@ private void addToImportEntriesGroup(List entriesToInsert) { if (preferences.getLibraryPreferences().isAddImportedEntriesEnabled()) { String groupName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); this.targetBibDatabaseContext.getMetaData() - .getGroups() - .flatMap(grp -> grp.getChildren() - .stream() - .filter(node -> node.getGroup() instanceof ExplicitGroup - && node.getGroup().getName().equals(groupName)) - .findFirst()) - .ifPresent(importGroup -> importGroup.addEntriesToGroup(entriesToInsert)); + .getGroups() + .flatMap(grp -> grp.getChildren() + .stream() + .filter(node -> node.getGroup() instanceof ExplicitGroup + && node.getGroup().getName().equals(groupName)) + .findFirst()) + .ifPresent(importGroup -> importGroup.addEntriesToGroup(entriesToInsert)); } } } From 50970ab41d58f7c5363a9d35b23dc0439f9becd9 Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 05:13:52 +0530 Subject: [PATCH 11/26] fixed importing issue --- .../java/org/jabref/logic/importer/util/GroupsParserTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index 7e91a479bd0..b44cee088da 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -9,6 +9,7 @@ import javafx.scene.paint.Color; import org.jabref.logic.auxparser.DefaultAuxParser; +import org.jabref.logic.exporter.GroupSerializer; import org.jabref.logic.importer.ParseException; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.field.StandardField; @@ -193,7 +194,7 @@ void roundtripSmartGroupToExplicitGroup() throws ParseException { assertEquals(ExplicitGroup.class, parsed.getClass()); // Store in new format (serialize) - org.jabref.logic.exporter.GroupSerializer serializer = new org.jabref.logic.exporter.GroupSerializer(); + GroupSerializer serializer = new GroupSerializer(); List serialized = serializer.serializeTree(GroupTreeNode.fromGroup(parsed)); String serializedString = serialized.get(0).substring(2); // Remove level prefix "0 " From 4024bf059865689658b6e0760209ed2324719ab2 Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 05:53:03 +0530 Subject: [PATCH 12/26] fixed openwrite by commenting out in rewrite.yml --- rewrite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rewrite.yml b/rewrite.yml index a993daa9452..2d03ec95d73 100644 --- a/rewrite.yml +++ b/rewrite.yml @@ -203,7 +203,7 @@ recipeList: # - org.openrewrite.staticanalysis.WriteOctalValuesAsDecimal # - org.openrewrite.java.testing.junit5.JUnit5BestPractices -- cannot be used directly, because one recipe is not working (see below) - - org.openrewrite.java.testing.cleanup.AssertLiteralBooleanToFailRecipe + # - org.openrewrite.java.testing.cleanup.AssertLiteralBooleanToFailRecipe - org.openrewrite.java.testing.cleanup.RemoveTestPrefix # - org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic -- does not work due to https://github.com/openrewrite/rewrite-testing-frameworks/issues/458 - org.openrewrite.java.testing.junit5.CleanupAssertions From 8720aa93a4d5ba9d2fa7dce09c5f55ff6dcd84a5 Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 06:11:38 +0530 Subject: [PATCH 13/26] runned rewriteRun gradel --- .../java/org/jabref/logic/importer/util/GroupsParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java index b44cee088da..3d6a87097f2 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/util/GroupsParserTest.java @@ -196,7 +196,7 @@ void roundtripSmartGroupToExplicitGroup() throws ParseException { // Store in new format (serialize) GroupSerializer serializer = new GroupSerializer(); List serialized = serializer.serializeTree(GroupTreeNode.fromGroup(parsed)); - String serializedString = serialized.get(0).substring(2); // Remove level prefix "0 " + String serializedString = serialized.getFirst().substring(2); // Remove level prefix "0 " // Verify it's stored as StaticGroup (ExplicitGroup format), not SmartGroup assertTrue(serializedString.startsWith("StaticGroup:")); From a989e729a904f06e755514fac4ee18104cf6de70 Mon Sep 17 00:00:00 2001 From: shubham kapoor Date: Wed, 26 Nov 2025 06:30:11 +0530 Subject: [PATCH 14/26] restoring rewrite.yml --- rewrite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rewrite.yml b/rewrite.yml index 2d03ec95d73..a993daa9452 100644 --- a/rewrite.yml +++ b/rewrite.yml @@ -203,7 +203,7 @@ recipeList: # - org.openrewrite.staticanalysis.WriteOctalValuesAsDecimal # - org.openrewrite.java.testing.junit5.JUnit5BestPractices -- cannot be used directly, because one recipe is not working (see below) - # - org.openrewrite.java.testing.cleanup.AssertLiteralBooleanToFailRecipe + - org.openrewrite.java.testing.cleanup.AssertLiteralBooleanToFailRecipe - org.openrewrite.java.testing.cleanup.RemoveTestPrefix # - org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic -- does not work due to https://github.com/openrewrite/rewrite-testing-frameworks/issues/458 - org.openrewrite.java.testing.junit5.CleanupAssertions From d881d3d404ca13d9fd583027d5742dae434bc208 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 30 Nov 2025 19:25:28 +0100 Subject: [PATCH 15/26] Remove duplicate test --- .../org/jabref/logic/exporter/GroupSerializerTest.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java b/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java index f16fa871214..24b10a0e563 100644 --- a/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java +++ b/jablib/src/test/java/org/jabref/logic/exporter/GroupSerializerTest.java @@ -53,14 +53,6 @@ void serializeSingleAllEntriesGroup() { assertEquals(List.of("0 AllEntriesGroup:"), serialization); } - @Test - void serializeExplicitGroupReplacesSmartGroup() { - // SmartGroup has been replaced by ExplicitGroup - ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, ','); - List serialization = groupSerializer.serializeTree(GroupTreeNode.fromGroup(group)); - assertEquals(List.of("0 StaticGroup:myExplicitGroup;0;1;;;;"), serialization); - } - @Test void serializeSingleExplicitGroup() { ExplicitGroup group = new ExplicitGroup("myExplicitGroup", GroupHierarchyType.INDEPENDENT, ','); From 691d5ebb3c333606ea0c11f6f90ecd8476e9c963 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 30 Nov 2025 19:26:47 +0100 Subject: [PATCH 16/26] refine comments --- .../java/org/jabref/logic/importer/util/GroupsParser.java | 2 +- .../jabref/logic/util/MetadataSerializationConfiguration.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index 047c2bb0618..9c1a31ccaf9 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -234,7 +234,7 @@ private static KeywordGroup keywordGroupFromString(String s, Character keywordSe /** * Migration method: Converts old SmartGroup serializations to ExplicitGroup. - * SmartGroup has been replaced by ExplicitGroup as they are functionally equivalent. + * SmartGroup has been replaced by ExplicitGroup for the "Imported Entries" group Issue 14143. */ private static ExplicitGroup smartGroupFromString(String input, Character keywordSeparator) throws ParseException { if (!input.startsWith(MetadataSerializationConfiguration.SMART_GROUP_ID)) { diff --git a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java index f7d601cc2fd..70dee15aa42 100644 --- a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java +++ b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java @@ -49,9 +49,11 @@ public class MetadataSerializationConfiguration { public static final String EXPLICIT_GROUP_ID = "StaticGroup:"; /** - * Identifier for {@link SmartGroup} (deprecated, replaced by {@link ExplicitGroup}). + * Identifier for SmartGroup (deprecated, replaced by {@link ExplicitGroup}). * Kept for backward compatibility during migration. + * */ + @Deprecated public static final String SMART_GROUP_ID = "SmartGroup:"; /** From 1293aa5e78c51e6d914240ef336cf2162229ed6b Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Sun, 30 Nov 2025 19:37:31 +0100 Subject: [PATCH 17/26] Undo changes to KeyCollisionException --- .../model/database/KeyCollisionException.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java index 354cabffe12..05bb346599c 100644 --- a/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java +++ b/jablib/src/main/java/org/jabref/model/database/KeyCollisionException.java @@ -1,36 +1,27 @@ package org.jabref.model.database; -import java.util.Objects; - -import org.jspecify.annotations.NonNull; - public class KeyCollisionException extends RuntimeException { - private static final String UNKNOWN_ID = ""; - - private final @NonNull String id; + private String id; public KeyCollisionException() { super(); - this.id = UNKNOWN_ID; } public KeyCollisionException(String msg, String id) { super(msg); - this.id = Objects.requireNonNullElse(id, UNKNOWN_ID); + this.id = id; } public KeyCollisionException(String msg, Throwable exception) { super(msg, exception); - this.id = UNKNOWN_ID; } public KeyCollisionException(Throwable exception) { super(exception); - this.id = UNKNOWN_ID; } - public @NonNull String getId() { + public String getId() { return id; } } From 3e8e072df18139ab9fd5bbef65f7851c6b96594c Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 30 Nov 2025 20:05:37 +0100 Subject: [PATCH 18/26] usse separator --- .../main/java/org/jabref/gui/groups/GroupTreeViewModel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index 29e210c40dc..8f4fa0ea7b6 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -187,8 +187,9 @@ private void addGroupImportEntries(GroupNodeViewModel parent) { return; } + char keywordSeparator = preferences.getBibEntryPreferences().getKeywordSeparator(); String grpName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); - AbstractGroup importEntriesGroup = new ExplicitGroup(grpName, GroupHierarchyType.INDEPENDENT, ','); + AbstractGroup importEntriesGroup = new ExplicitGroup(grpName, GroupHierarchyType.INDEPENDENT, keywordSeparator); boolean isGrpExist = parent.getGroupNode() .getChildren() .stream() From e8094af4bda52a574ad88cf8f01a7d4aac9ce95c Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 30 Nov 2025 20:18:39 +0100 Subject: [PATCH 19/26] Fix variable names --- .../org/jabref/gui/groups/GroupTreeViewModel.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index 8f4fa0ea7b6..1788ee62841 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -187,16 +187,16 @@ private void addGroupImportEntries(GroupNodeViewModel parent) { return; } - char keywordSeparator = preferences.getBibEntryPreferences().getKeywordSeparator(); - String grpName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); - AbstractGroup importEntriesGroup = new ExplicitGroup(grpName, GroupHierarchyType.INDEPENDENT, keywordSeparator); - boolean isGrpExist = parent.getGroupNode() + String groupName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); + boolean groupExists = parent.getGroupNode() .getChildren() .stream() .map(GroupTreeNode::getGroup) - .anyMatch(grp -> grp instanceof ExplicitGroup && grp.getName().equals(grpName)); - if (!isGrpExist) { + .anyMatch(grp -> grp instanceof ExplicitGroup && grp.getName().equals(groupName)); + if (!groupExists) { currentDatabase.ifPresent(db -> { + char keywordSeparator = preferences.getBibEntryPreferences().getKeywordSeparator(); + AbstractGroup importEntriesGroup = new ExplicitGroup(groupName, GroupHierarchyType.INDEPENDENT, keywordSeparator); GroupTreeNode newSubgroup = parent.addSubgroup(importEntriesGroup); newSubgroup.moveTo(parent.getGroupNode(), 0); selectedGroups.setAll(new GroupNodeViewModel(db, stateManager, taskExecutor, newSubgroup, localDragboard, preferences)); From 7a9d9147c1b511c6d55e6f0db5a25f2036640ce5 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 30 Nov 2025 20:20:52 +0100 Subject: [PATCH 20/26] Use _ --- .../src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index 1788ee62841..f2068e36e63 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -179,7 +179,7 @@ private void onActiveDatabaseChanged(Optional newDatabase) { rootGroup.setValue(null); } currentDatabase = newDatabase; - newDatabase.ifPresent(db -> addGroupImportEntries(rootGroup.get())); + newDatabase.ifPresent(_ -> addGroupImportEntries(rootGroup.get())); } private void addGroupImportEntries(GroupNodeViewModel parent) { From e7e23dfb6590d359bfcf743e973fd111e1681d68 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 30 Nov 2025 20:30:56 +0100 Subject: [PATCH 21/26] Fix name --- .../java/org/jabref/gui/collab/groupchange/GroupChange.java | 4 ++-- .../main/java/org/jabref/gui/groups/GroupNodeViewModel.java | 2 +- .../java/org/jabref/migrations/ConvertMarkingToGroups.java | 2 +- .../org/jabref/migrations/ConvertMarkingToGroupsTest.java | 2 +- .../org/jabref/logic/bibtex/comparator/MetaDataDiff.java | 2 +- .../src/main/java/org/jabref/logic/groups/GroupsFactory.java | 5 +---- .../org/jabref/logic/importer/fileformat/BibtexParser.java | 2 +- .../java/org/jabref/logic/importer/util/GroupsParser.java | 2 +- .../org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java | 4 ++-- 9 files changed, 11 insertions(+), 14 deletions(-) diff --git a/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java b/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java index 638a0d44e58..addc86a9ecc 100644 --- a/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java +++ b/jabgui/src/main/java/org/jabref/gui/collab/groupchange/GroupChange.java @@ -27,7 +27,7 @@ public void applyChange(NamedCompoundEdit undoEdit) { GroupTreeNode newRoot = groupDiff.getNewGroupRoot(); GroupTreeNode root = databaseContext.getMetaData().getGroups().orElseGet(() -> { - GroupTreeNode groupTreeNode = new GroupTreeNode(GroupsFactory.getAllEntriesGroup()); + GroupTreeNode groupTreeNode = new GroupTreeNode(GroupsFactory.createAllEntriesGroup()); databaseContext.getMetaData().setGroups(groupTreeNode); return groupTreeNode; }); @@ -38,7 +38,7 @@ public void applyChange(NamedCompoundEdit undoEdit) { root.removeAllChildren(); if (newRoot == null) { // I think setting root to null is not possible - root.setGroup(GroupsFactory.getAllEntriesGroup(), false, false, null); + root.setGroup(GroupsFactory.createAllEntriesGroup(), false, false, null); } else { // change root group, even though it'll be AllEntries anyway root.setGroup(newRoot.getGroup(), false, false, null); diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index 6a63caab844..ed9052ddd60 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -140,7 +140,7 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state } static GroupNodeViewModel getAllEntriesGroup(BibDatabaseContext newDatabase, StateManager stateManager, TaskExecutor taskExecutor, CustomLocalDragboard localDragBoard, GuiPreferences preferences) { - return new GroupNodeViewModel(newDatabase, stateManager, taskExecutor, GroupsFactory.getAllEntriesGroup(), localDragBoard, preferences); + return new GroupNodeViewModel(newDatabase, stateManager, taskExecutor, GroupsFactory.createAllEntriesGroup(), localDragBoard, preferences); } private GroupNodeViewModel toViewModel(GroupTreeNode child) { diff --git a/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java b/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java index 924027713ba..03c68e924f3 100644 --- a/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java +++ b/jabgui/src/main/java/org/jabref/migrations/ConvertMarkingToGroups.java @@ -48,7 +48,7 @@ public void performMigration(@NonNull ParserResult parserResult) { } if (parserResult.getMetaData().getGroups().isEmpty()) { - parserResult.getMetaData().setGroups(GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup())); + parserResult.getMetaData().setGroups(GroupTreeNode.fromGroup(GroupsFactory.createAllEntriesGroup())); } GroupTreeNode root = parserResult.getMetaData().getGroups().get(); root.addChild(markingRoot, 0); diff --git a/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java b/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java index e0a0ac05a2e..e64ccdfec73 100644 --- a/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java +++ b/jabgui/src/test/java/org/jabref/migrations/ConvertMarkingToGroupsTest.java @@ -24,7 +24,7 @@ void performMigrationForSingleEntry() { new ConvertMarkingToGroups().performMigration(parserResult); - GroupTreeNode rootExpected = GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup()); + GroupTreeNode rootExpected = GroupTreeNode.fromGroup(GroupsFactory.createAllEntriesGroup()); GroupTreeNode markings = rootExpected.addSubgroup(new ExplicitGroup("Markings", GroupHierarchyType.INCLUDING, ',')); markings.addSubgroup(new ExplicitGroup("Nicolas:6", GroupHierarchyType.INCLUDING, ',')); diff --git a/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java b/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java index b122719bffa..20f0b66770a 100644 --- a/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java +++ b/jablib/src/main/java/org/jabref/logic/bibtex/comparator/MetaDataDiff.java @@ -94,7 +94,7 @@ private boolean isDefaultGroup(Optional groups) { if (!groupRoot.getChildren().isEmpty()) { return false; } - return groupRoot.getGroup().equals(GroupsFactory.getAllEntriesGroup()); + return groupRoot.getGroup().equals(GroupsFactory.createAllEntriesGroup()); } /** diff --git a/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java b/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java index 2f3384a2f9b..09fa3f3d98e 100644 --- a/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java +++ b/jablib/src/main/java/org/jabref/logic/groups/GroupsFactory.java @@ -8,9 +8,6 @@ import org.jabref.model.groups.SearchGroup; import org.jabref.model.search.SearchFlags; -/** - * This factory creates groups. - */ public class GroupsFactory { public static final String ALL_ENTRIES_GROUP_DEFAULT_ICON = "ALL_ENTRIES_GROUP_ICON"; @@ -18,7 +15,7 @@ public class GroupsFactory { private GroupsFactory() { } - public static AllEntriesGroup getAllEntriesGroup() { + public static AllEntriesGroup createAllEntriesGroup() { AllEntriesGroup group = new AllEntriesGroup(Localization.lang("All entries")); group.setIconName(ALL_ENTRIES_GROUP_DEFAULT_ICON); return group; diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java index cf9fb1217b1..ee1c4441506 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java @@ -290,7 +290,7 @@ private ParserResult parseFileContent() throws IOException { }, // metadata does not contain any groups, so we need to create an AllEntriesGroup and add the other groups as children () -> { - GroupTreeNode rootNode = new GroupTreeNode(GroupsFactory.getAllEntriesGroup()); + GroupTreeNode rootNode = new GroupTreeNode(GroupsFactory.createAllEntriesGroup()); bibDeskGroupTreeNode.moveTo(rootNode); metaData.setGroups(rootNode); } diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index 9c1a31ccaf9..813159c595c 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -307,7 +307,7 @@ private static AbstractGroup allEntriesGroupFromString(String s) { if (!s.startsWith(MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID)) { throw new IllegalArgumentException("AllEntriesGroup cannot be created from \"" + s + "\"."); } - return GroupsFactory.getAllEntriesGroup(); + return GroupsFactory.createAllEntriesGroup(); } /** diff --git a/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java b/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java index 438ecc7229a..cf74944b46a 100644 --- a/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java +++ b/jablib/src/test/java/org/jabref/logic/bibtex/comparator/MetaDataDiffTest.java @@ -43,7 +43,7 @@ void defaultSettingEqualsEmptySetting() { @Test void allEntriesGroupIgnored() { MetaData one = new MetaData(); - one.setGroups(GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup())); + one.setGroups(GroupTreeNode.fromGroup(GroupsFactory.createAllEntriesGroup())); MetaData two = new MetaData(); assertEquals(Optional.empty(), MetaDataDiff.compare(one, two)); @@ -52,7 +52,7 @@ void allEntriesGroupIgnored() { @Test void allEntriesGroupContainingGroupNotIgnored() { MetaData one = new MetaData(); - GroupTreeNode root = GroupTreeNode.fromGroup(GroupsFactory.getAllEntriesGroup()); + GroupTreeNode root = GroupTreeNode.fromGroup(GroupsFactory.createAllEntriesGroup()); root.addSubgroup(new ExplicitGroup("ExplicitA", GroupHierarchyType.INCLUDING, ',')); one.setGroups(root); From fe98c8b3179624ea5803232f21f433d60cff2eb4 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Sun, 30 Nov 2025 20:48:05 +0100 Subject: [PATCH 22/26] Reduce scope of migration constant and remove superfluous throws --- .../logic/importer/util/GroupsParser.java | 230 +++++++++--------- .../MetadataSerializationConfiguration.java | 8 - 2 files changed, 112 insertions(+), 126 deletions(-) diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index 9c1a31ccaf9..3073de55380 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -41,12 +41,24 @@ */ public class GroupsParser { + /** + * Identifier for SmartGroup (deprecated, replaced by {@link ExplicitGroup}). + * Kept for backward compatibility during migration. + * + */ + @Deprecated + private static final String SMART_GROUP_ID_FOR_MIGRATION = "SmartGroup:"; + private static final Logger LOGGER = LoggerFactory.getLogger(GroupsParser.class); private GroupsParser() { } - public static GroupTreeNode importGroups(List orderedData, Character keywordSeparator, FileUpdateMonitor fileMonitor, MetaData metaData, String userAndHost) + public static GroupTreeNode importGroups(List orderedData, + Character keywordSeparator, + FileUpdateMonitor fileMonitor, + MetaData metaData, + String userAndHost) throws ParseException { try { GroupTreeNode cursor = null; @@ -89,65 +101,67 @@ public static GroupTreeNode importGroups(List orderedData, Character key /** * Re-create a group instance from a textual representation. * - * @param s The result from the group's toString() method. + * @param input The result from the group's toString() method. * @return New instance of the encoded group. * @throws ParseException If an error occurred and a group could not be created, e.g. due to a malformed regular expression. */ - public static AbstractGroup fromString(String s, Character keywordSeparator, FileUpdateMonitor fileMonitor, MetaData metaData, String userAndHost) + public static AbstractGroup fromString(String input, Character keywordSeparator, FileUpdateMonitor fileMonitor, MetaData metaData, String userAndHost) throws ParseException { - if (s.startsWith(MetadataSerializationConfiguration.KEYWORD_GROUP_ID)) { - return keywordGroupFromString(s, keywordSeparator); + if (input.startsWith(MetadataSerializationConfiguration.KEYWORD_GROUP_ID)) { + return keywordGroupFromString(input, keywordSeparator); } - if (s.startsWith(MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID)) { - return allEntriesGroupFromString(s); + if (input.startsWith(MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID)) { + return allEntriesGroupFromString(input); } - if (s.startsWith(MetadataSerializationConfiguration.SMART_GROUP_ID)) { + if (input.startsWith(SMART_GROUP_ID_FOR_MIGRATION)) { // Migration: SmartGroup is replaced by ExplicitGroup - return smartGroupFromString(s, keywordSeparator); + return smartGroupFromString(input, keywordSeparator); } - if (s.startsWith(MetadataSerializationConfiguration.SEARCH_GROUP_ID)) { - return searchGroupFromString(s); + if (input.startsWith(MetadataSerializationConfiguration.SEARCH_GROUP_ID)) { + return searchGroupFromString(input); } - if (s.startsWith(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID)) { - return explicitGroupFromString(s, keywordSeparator); + if (input.startsWith(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID)) { + return explicitGroupFromString(input, keywordSeparator); } - if (s.startsWith(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID)) { - return legacyExplicitGroupFromString(s, keywordSeparator); + if (input.startsWith(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID)) { + return legacyExplicitGroupFromString(input, keywordSeparator); } - if (s.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID)) { - return automaticPersonsGroupFromString(s); + if (input.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID)) { + return automaticPersonsGroupFromString(input); } - if (s.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID)) { - return automaticKeywordGroupFromString(s); + if (input.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID)) { + return automaticKeywordGroupFromString(input); } - if (s.startsWith(MetadataSerializationConfiguration.AUTOMATIC_DATE_GROUP_ID)) { - return automaticDateGroupFromString(s); + if (input.startsWith(MetadataSerializationConfiguration.AUTOMATIC_DATE_GROUP_ID)) { + return automaticDateGroupFromString(input); } - if (s.startsWith(MetadataSerializationConfiguration.TEX_GROUP_ID)) { - return texGroupFromString(s, fileMonitor, metaData, userAndHost); + if (input.startsWith(MetadataSerializationConfiguration.TEX_GROUP_ID)) { + return texGroupFromString(input, fileMonitor, metaData, userAndHost); } - throw new ParseException("Unknown group: " + s); + throw new ParseException("Unknown group: " + input); } - private static AbstractGroup texGroupFromString(String string, FileUpdateMonitor fileMonitor, MetaData metaData, String userAndHost) throws ParseException { - QuotedStringTokenizer tok = new QuotedStringTokenizer(string.substring(MetadataSerializationConfiguration.TEX_GROUP_ID + private static AbstractGroup texGroupFromString(String input, FileUpdateMonitor fileMonitor, MetaData metaData, String userAndHost) throws ParseException { + assert input.startsWith(MetadataSerializationConfiguration.TEX_GROUP_ID); + + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.TEX_GROUP_ID .length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(token.nextToken())); try { - Path path = Path.of(tok.nextToken()); + Path path = Path.of(token.nextToken()); try { TexGroup newGroup = TexGroup.create(name, context, path, new DefaultAuxParser(new BibDatabase()), fileMonitor, metaData, userAndHost); - addGroupDetails(tok, newGroup); + addGroupDetails(token, newGroup); return newGroup; } catch (IOException ex) { // Problem accessing file -> create without file monitoring LOGGER.warn("Could not access file {}. The group {} will not reflect changes to the aux file.", path, name, ex); TexGroup newGroup = TexGroup.create(name, context, path, new DefaultAuxParser(new BibDatabase()), metaData, userAndHost); - addGroupDetails(tok, newGroup); + addGroupDetails(token, newGroup); return newGroup; } } catch (InvalidPathException | IOException ex) { @@ -155,80 +169,76 @@ private static AbstractGroup texGroupFromString(String string, FileUpdateMonitor } } - private static AbstractGroup automaticPersonsGroupFromString(String string) { - if (!string.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID)) { - throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + string + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(string.substring(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID + private static AbstractGroup automaticPersonsGroupFromString(String input) { + assert input.startsWith(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID); + + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.AUTOMATIC_PERSONS_GROUP_ID .length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); - Field field = FieldFactory.parseField(StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(token.nextToken())); + Field field = FieldFactory.parseField(StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); AutomaticPersonsGroup newGroup = new AutomaticPersonsGroup(name, context, field); - addGroupDetails(tok, newGroup); + addGroupDetails(token, newGroup); return newGroup; } - private static AbstractGroup automaticDateGroupFromString(String string) { - if (!string.startsWith(MetadataSerializationConfiguration.AUTOMATIC_DATE_GROUP_ID)) { - throw new IllegalArgumentException("AutomaticDateGroup cannot be created from \"" + string + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(string.substring(MetadataSerializationConfiguration.AUTOMATIC_DATE_GROUP_ID + private static AbstractGroup automaticDateGroupFromString(String input) { + assert input.startsWith(MetadataSerializationConfiguration.AUTOMATIC_DATE_GROUP_ID); + + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.AUTOMATIC_DATE_GROUP_ID .length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); - Field field = FieldFactory.parseField(StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); - String granularityString = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(token.nextToken())); + Field field = FieldFactory.parseField(StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); + String granularityString = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); DateGranularity granularity = DateGranularity.valueOf(granularityString); AutomaticDateGroup newGroup = new AutomaticDateGroup(name, context, field, granularity); - addGroupDetails(tok, newGroup); + addGroupDetails(token, newGroup); return newGroup; } - private static AbstractGroup automaticKeywordGroupFromString(String string) { - if (!string.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID)) { - throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + string + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(string.substring(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID + private static AbstractGroup automaticKeywordGroupFromString(String input) { + assert input.startsWith(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID); + + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.AUTOMATIC_KEYWORD_GROUP_ID .length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); - Field field = FieldFactory.parseField(StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); - Character delimiter = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR).charAt(0); - Character hierarchicalDelimiter = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR).charAt(0); + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(token.nextToken())); + Field field = FieldFactory.parseField(StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); + Character delimiter = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR).charAt(0); + Character hierarchicalDelimiter = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR).charAt(0); AutomaticKeywordGroup newGroup = new AutomaticKeywordGroup(name, context, field, delimiter, hierarchicalDelimiter); - addGroupDetails(tok, newGroup); + addGroupDetails(token, newGroup); return newGroup; } /** * Parses s and recreates the KeywordGroup from it. * - * @param s The String representation obtained from KeywordGroup.toString() + * @param input The String representation obtained from KeywordGroup.toString() */ - private static KeywordGroup keywordGroupFromString(String s, Character keywordSeparator) { - if (!s.startsWith(MetadataSerializationConfiguration.KEYWORD_GROUP_ID)) { - throw new IllegalArgumentException("KeywordGroup cannot be created from \"" + s + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(s.substring(MetadataSerializationConfiguration.KEYWORD_GROUP_ID + private static KeywordGroup keywordGroupFromString(String input, Character keywordSeparator) { + assert input.startsWith(MetadataSerializationConfiguration.KEYWORD_GROUP_ID); + + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.KEYWORD_GROUP_ID .length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(tok.nextToken())); - Field field = FieldFactory.parseField(StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); - String expression = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - boolean caseSensitive = Integer.parseInt(tok.nextToken()) == 1; - boolean regExp = Integer.parseInt(tok.nextToken()) == 1; + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + GroupHierarchyType context = GroupHierarchyType.getByNumberOrDefault(Integer.parseInt(token.nextToken())); + Field field = FieldFactory.parseField(StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR)); + String expression = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + boolean caseSensitive = Integer.parseInt(token.nextToken()) == 1; + boolean regExp = Integer.parseInt(token.nextToken()) == 1; KeywordGroup newGroup; if (regExp) { newGroup = new RegexKeywordGroup(name, context, field, expression, caseSensitive); } else { newGroup = new WordKeywordGroup(name, context, field, expression, caseSensitive, keywordSeparator, false); } - addGroupDetails(tok, newGroup); + addGroupDetails(token, newGroup); return newGroup; } @@ -237,35 +247,23 @@ private static KeywordGroup keywordGroupFromString(String s, Character keywordSe * SmartGroup has been replaced by ExplicitGroup for the "Imported Entries" group Issue 14143. */ private static ExplicitGroup smartGroupFromString(String input, Character keywordSeparator) throws ParseException { - if (!input.startsWith(MetadataSerializationConfiguration.SMART_GROUP_ID)) { - throw new IllegalArgumentException("SmartGroup cannot be created from \"" + input + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.SMART_GROUP_ID.length()), - MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + assert input.startsWith(SMART_GROUP_ID_FOR_MIGRATION); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - try { - int context = Integer.parseInt(tok.nextToken()); - ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); - addGroupDetails(tok, newGroup); - return newGroup; - } catch (NumberFormatException exception) { - throw new ParseException("Could not parse context in " + input); - } + input = input.replace(SMART_GROUP_ID_FOR_MIGRATION, MetadataSerializationConfiguration.EXPLICIT_GROUP_ID); + return explicitGroupFromString(input, keywordSeparator); } private static ExplicitGroup explicitGroupFromString(String input, Character keywordSeparator) throws ParseException { - if (!input.startsWith(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID)) { - throw new IllegalArgumentException("ExplicitGroup cannot be created from \"" + input + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID.length()), + assert input.startsWith(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID); + + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.EXPLICIT_GROUP_ID.length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); try { - int context = Integer.parseInt(tok.nextToken()); + int context = Integer.parseInt(token.nextToken()); ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); - addGroupDetails(tok, newGroup); + addGroupDetails(token, newGroup); return newGroup; } catch (NumberFormatException exception) { throw new ParseException("Could not parse context in " + input); @@ -273,17 +271,16 @@ private static ExplicitGroup explicitGroupFromString(String input, Character key } private static ExplicitGroup legacyExplicitGroupFromString(String input, Character keywordSeparator) throws ParseException { - if (!input.startsWith(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID)) { - throw new IllegalArgumentException("ExplicitGroup cannot be created from \"" + input + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID.length()), + assert input.startsWith(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID); + + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.LEGACY_EXPLICIT_GROUP_ID.length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); try { - int context = Integer.parseInt(tok.nextToken()); + int context = Integer.parseInt(token.nextToken()); ExplicitGroup newGroup = new ExplicitGroup(name, GroupHierarchyType.getByNumberOrDefault(context), keywordSeparator); - GroupsParser.addLegacyEntryKeys(tok, newGroup); + GroupsParser.addLegacyEntryKeys(token, newGroup); return newGroup; } catch (NumberFormatException exception) { throw new ParseException("Could not parse context in " + input); @@ -303,33 +300,30 @@ private static void addLegacyEntryKeys(QuotedStringTokenizer tok, ExplicitGroup } } - private static AbstractGroup allEntriesGroupFromString(String s) { - if (!s.startsWith(MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID)) { - throw new IllegalArgumentException("AllEntriesGroup cannot be created from \"" + s + "\"."); - } + private static AbstractGroup allEntriesGroupFromString(String input) { + assert input.startsWith(MetadataSerializationConfiguration.ALL_ENTRIES_GROUP_ID); + return GroupsFactory.getAllEntriesGroup(); } /** * Parses s and recreates the SearchGroup from it. * - * @param s The String representation obtained from SearchGroup.toString(), or null if incompatible + * @param input The String representation obtained from SearchGroup.toString(), or null if incompatible */ - private static AbstractGroup searchGroupFromString(String s) { - if (!s.startsWith(MetadataSerializationConfiguration.SEARCH_GROUP_ID)) { - throw new IllegalArgumentException("SearchGroup cannot be created from \"" + s + "\"."); - } - QuotedStringTokenizer tok = new QuotedStringTokenizer(s.substring(MetadataSerializationConfiguration.SEARCH_GROUP_ID.length()), + private static AbstractGroup searchGroupFromString(String input) { + assert input.startsWith(MetadataSerializationConfiguration.SEARCH_GROUP_ID); + QuotedStringTokenizer token = new QuotedStringTokenizer(input.substring(MetadataSerializationConfiguration.SEARCH_GROUP_ID.length()), MetadataSerializationConfiguration.GROUP_UNIT_SEPARATOR, MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - String name = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); - int context = Integer.parseInt(tok.nextToken()); - String expression = StringUtil.unquote(tok.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + String name = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); + int context = Integer.parseInt(token.nextToken()); + String expression = StringUtil.unquote(token.nextToken(), MetadataSerializationConfiguration.GROUP_QUOTE_CHAR); EnumSet searchFlags = EnumSet.noneOf(SearchFlags.class); - if (Integer.parseInt(tok.nextToken()) == 1) { + if (Integer.parseInt(token.nextToken()) == 1) { searchFlags.add(SearchFlags.CASE_SENSITIVE); } - if (Integer.parseInt(tok.nextToken()) == 1) { + if (Integer.parseInt(token.nextToken()) == 1) { searchFlags.add(SearchFlags.REGULAR_EXPRESSION); } // version 0 contained 4 additional booleans to specify search @@ -337,7 +331,7 @@ private static AbstractGroup searchGroupFromString(String s) { SearchGroup searchGroup = new SearchGroup(name, GroupHierarchyType.getByNumberOrDefault(context), expression, searchFlags ); - addGroupDetails(tok, searchGroup); + addGroupDetails(token, searchGroup); return searchGroup; } diff --git a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java index 70dee15aa42..a475a70b80a 100644 --- a/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java +++ b/jablib/src/main/java/org/jabref/logic/util/MetadataSerializationConfiguration.java @@ -48,14 +48,6 @@ public class MetadataSerializationConfiguration { */ public static final String EXPLICIT_GROUP_ID = "StaticGroup:"; - /** - * Identifier for SmartGroup (deprecated, replaced by {@link ExplicitGroup}). - * Kept for backward compatibility during migration. - * - */ - @Deprecated - public static final String SMART_GROUP_ID = "SmartGroup:"; - /** * Identifier for {@link SearchGroup}. */ From b8d1cc4141d10d0ea587f48c74beec714c5ed984 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 30 Nov 2025 20:50:52 +0100 Subject: [PATCH 23/26] add hint --- .../main/java/org/jabref/gui/externalfiles/ImportHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java index 596c6f1b0b4..eff6b7bb250 100644 --- a/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java +++ b/jabgui/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java @@ -534,6 +534,8 @@ private List handlePdfUrl(String pdfUrl) throws IOException { private void addToImportEntriesGroup(List entriesToInsert) { if (preferences.getLibraryPreferences().isAddImportedEntriesEnabled()) { String groupName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); + // We cannot add the new group here directly because we don't have access to the group node viewmoel stuff here + // We would need to add the groups to the metadata first which is a bit more complicated, thus we decided against it atm this.targetBibDatabaseContext.getMetaData() .getGroups() .flatMap(grp -> grp.getChildren() From 75681462112cce774a7a5cb8ce6084e51150aacb Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 30 Nov 2025 21:02:02 +0100 Subject: [PATCH 24/26] Fix format --- .../java/org/jabref/gui/groups/GroupTreeViewModel.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index f2068e36e63..2aaf3ac3977 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -189,10 +189,10 @@ private void addGroupImportEntries(GroupNodeViewModel parent) { String groupName = preferences.getLibraryPreferences().getAddImportedEntriesGroupName(); boolean groupExists = parent.getGroupNode() - .getChildren() - .stream() - .map(GroupTreeNode::getGroup) - .anyMatch(grp -> grp instanceof ExplicitGroup && grp.getName().equals(groupName)); + .getChildren() + .stream() + .map(GroupTreeNode::getGroup) + .anyMatch(grp -> grp instanceof ExplicitGroup && grp.getName().equals(groupName)); if (!groupExists) { currentDatabase.ifPresent(db -> { char keywordSeparator = preferences.getBibEntryPreferences().getKeywordSeparator(); From dfe948f66868f03d1a910cfb7d8f5c3fc5042aa2 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 30 Nov 2025 21:08:12 +0100 Subject: [PATCH 25/26] Add `@deprecated` --- .../main/java/org/jabref/logic/importer/util/GroupsParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java index 5832e8046dd..8ce056292c0 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/GroupsParser.java @@ -43,8 +43,8 @@ public class GroupsParser { /** * Identifier for SmartGroup (deprecated, replaced by {@link ExplicitGroup}). - * Kept for backward compatibility during migration. * + * @deprecated Kept for backward compatibility during migration. */ @Deprecated private static final String SMART_GROUP_ID_FOR_MIGRATION = "SmartGroup:"; From 44fc1cb43655ee630e4bdcd68ca6eed3b08a5526 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 30 Nov 2025 21:41:53 +0100 Subject: [PATCH 26/26] Fix tests --- .../java/org/jabref/gui/groups/GroupTreeViewModelTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java b/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java index d660a7f030d..5c05e061835 100644 --- a/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java +++ b/jabgui/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java @@ -17,6 +17,7 @@ import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.BibEntryPreferences; import org.jabref.model.entry.field.StandardField; import org.jabref.model.groups.AbstractGroup; import org.jabref.model.groups.AllEntriesGroup; @@ -64,6 +65,9 @@ void setUp() { true, true, GroupHierarchyType.INDEPENDENT)); + BibEntryPreferences bibEntryPreferences = mock(BibEntryPreferences.class); + when(bibEntryPreferences.getKeywordSeparator()).thenReturn(','); + when(preferences.getBibEntryPreferences()).thenReturn(bibEntryPreferences); groupTree = new GroupTreeViewModel(stateManager, mock(DialogService.class), mock(AiService.class), preferences, mock(AdaptVisibleTabs.class), taskExecutor, new CustomLocalDragboard()); }