Skip to content

Refine GroupsTree#15013

Merged
Siedlerchr merged 4 commits into
mainfrom
refine-groups-tree
Feb 3, 2026
Merged

Refine GroupsTree#15013
Siedlerchr merged 4 commits into
mainfrom
refine-groups-tree

Conversation

@koppor

@koppor koppor commented Feb 3, 2026

Copy link
Copy Markdown
Member

User description

Small code update

Mandatory checks

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • [/] I added JUnit tests for changes (if applicable)
  • [/] I added screenshots in the PR description (if change is visible to the user)
  • [/] I described the change in CHANGELOG.md in a way that is understandable for the average user (if change is visible to the user)
  • [/] I checked the user documentation: Is the information available and up to date? If not, I created an issue at https://github.com/JabRef/user-documentation/issues or, even better, I submitted a pull request updating file(s) in https://github.com/JabRef/user-documentation/tree/main/en.

PR Type

Enhancement


Description

  • Replace ArrayList with List interface for better abstraction

  • Use instanceof pattern matching to simplify type casting

  • Extract variable to reduce repeated method calls

  • Add logging for unsupported group entry removal operations


Diagram Walkthrough

flowchart LR
  A["Code Improvements"] --> B["Type Abstraction"]
  A --> C["Pattern Matching"]
  A --> D["Variable Extraction"]
  A --> E["Logging"]
  B --> F["ArrayList to List"]
  C --> G["instanceof with casting"]
  D --> H["Reduce method calls"]
  E --> I["Warn on unsupported ops"]
Loading

File Walkthrough

Relevant files
Enhancement
GroupTreeViewModel.java
Use interface type and extract variable                                   

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java

  • Changed ArrayList declarations to List interface type in two methods
  • Extracted BibDatabaseContext variable to avoid repeated
    currentDatabase.get() calls
  • Improved code reusability by using the extracted variable in multiple
    locations
+5/-4     
GroupTreeNode.java
Add logging and use instanceof pattern matching                   

jablib/src/main/java/org/jabref/model/groups/GroupTreeNode.java

  • Added SLF4J logger import and static logger field initialization
  • Replaced traditional instanceof cast with pattern matching syntax
  • Added warning log message when attempting to remove entries from
    unsupported group types
  • Simplified type casting by using the pattern-matched variable directly
+7/-2     

@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Sensitive information exposure

Description: The warning log at line 295 may expose sensitive information through getGroup().getName(),
potentially revealing internal group structure or naming conventions to unauthorized
parties if logs are accessible.
GroupTreeNode.java [295-295]

Referred Code
LOGGER.warn("Tried to remove entries from a group that does not support entry changing: {}", getGroup().getName());
return List.of();
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@koppor koppor added dev: code-quality Issues related to code or architecture decisions status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers and removed Review effort 2/5 labels Feb 3, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Enhance logging with group type

Enhance the warning log in removeEntriesFromGroup to include the group's type
for more informative debugging.

jablib/src/main/java/org/jabref/model/groups/GroupTreeNode.java [291-298]

     public List<FieldChange> removeEntriesFromGroup(List<BibEntry> entries) {
--        if (getGroup() instanceof GroupEntryChanger) {
--            return ((GroupEntryChanger) getGroup()).remove(entries);
-+        if (getGroup() instanceof GroupEntryChanger entryChanger) {
-+            return entryChanger.remove(entries);
-         } else {
-+            LOGGER.warn("Tried to remove entries from a group that does not support entry changing: {}", getGroup().getName());
-             return List.of();
-         }
-     }
+        if (getGroup() instanceof GroupEntryChanger entryChanger) {
+            return entryChanger.remove(entries);
+        } else {
+            LOGGER.warn("Tried to remove entries from group '{}' of type '{}', which does not support entry changing.", getGroup().getName(), getGroup().getClass().getName());
+            return List.of();
+        }
+    }
  • Apply / Chat
Suggestion importance[1-10]: 4

__

Why: The suggestion improves a newly added log message by including the group's type, which can be helpful for debugging, making it a good but minor code quality enhancement.

Low
  • More

@koppor koppor marked this pull request as draft February 3, 2026 11:19
@koppor koppor removed the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Feb 3, 2026
@koppor koppor changed the title Use instanceOf matcher Refine GroupsTree Feb 3, 2026
@koppor koppor marked this pull request as ready for review February 3, 2026 12:51
@koppor koppor added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Feb 3, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix incorrect Optional handling

Correct the handling of the currentDatabase optional. The new code introduces a
compilation error by incorrectly assigning an Optional to a raw type; wrap the
logic in an ifPresent check to fix this and avoid potential runtime exceptions.

jabgui/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java [667-686]

 void removeGroupsAndSubGroupsFromEntries(GroupNodeViewModel group) {
     for (GroupNodeViewModel child : group.getChildren()) {
         removeGroupsAndSubGroupsFromEntries(child);
     }
 
     // only remove explicit groups from the entries, keyword groups should not be deleted
     if (group.getGroupNode().getGroup() instanceof ExplicitGroup) {
-        int groupsWithSameName = 0;
-        String name = group.getGroupNode().getGroup().getName();
-        BibDatabaseContext bibDatabaseContext = currentDatabase.get();
-        Optional<GroupTreeNode> rootGroup = bibDatabaseContext.getMetaData().getGroups();
-        if (rootGroup.isPresent()) {
-            groupsWithSameName = rootGroup.get().findChildrenSatisfying(g -> g.getName().equals(name)).size();
-        }
-        if (groupsWithSameName < 2) {
-            List<BibEntry> entriesInGroup = group.getGroupNode().getEntriesInGroup(bibDatabaseContext.getEntries());
-            group.getGroupNode().removeEntriesFromGroup(entriesInGroup);
-        }
+        currentDatabase.get().ifPresent(bibDatabaseContext -> {
+            int groupsWithSameName = 0;
+            String name = group.getGroupNode().getGroup().getName();
+            Optional<GroupTreeNode> rootGroup = bibDatabaseContext.getMetaData().getGroups();
+            if (rootGroup.isPresent()) {
+                groupsWithSameName = rootGroup.get().findChildrenSatisfying(g -> g.getName().equals(name)).size();
+            }
+            if (groupsWithSameName < 2) {
+                List<BibEntry> entriesInGroup = group.getGroupNode().getEntriesInGroup(bibDatabaseContext.getEntries());
+                group.getGroupNode().removeEntriesFromGroup(entriesInGroup);
+            }
+        });
     }
 }

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies that the refactoring in the PR introduced a compilation error by assigning an Optional<BibDatabaseContext> to a BibDatabaseContext variable. The proposed fix correctly wraps the logic in an ifPresent block, resolving the compile error and preventing a potential NoSuchElementException at runtime.

High
Learned
best practice
Add logging level check

The logger statement is correctly using parameterized logging with a
placeholder. However, getGroup().getName() will be evaluated even if WARN level
logging is disabled. Consider checking if logging is enabled before calling
getName() for better performance.

jablib/src/main/java/org/jabref/model/groups/GroupTreeNode.java [295]

-LOGGER.warn("Tried to remove entries from a group that does not support entry changing: {}", getGroup().getName());
+if (LOGGER.isWarnEnabled()) {
+    LOGGER.warn("Tried to remove entries from a group that does not support entry changing: {}", getGroup().getName());
+}
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Use SLF4J parameterized logging instead of string concatenation to improve performance and avoid unnecessary string construction when logging is disabled.

Low
  • More

@koppor koppor mentioned this pull request Feb 3, 2026
5 tasks
@Siedlerchr Siedlerchr added this pull request to the merge queue Feb 3, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Feb 3, 2026
Merged via the queue into main with commit 97e325d Feb 3, 2026
73 of 84 checks passed
@Siedlerchr Siedlerchr deleted the refine-groups-tree branch February 3, 2026 19:38
Siedlerchr added a commit that referenced this pull request Feb 4, 2026
* upstream/main:
  New Crowdin updates (#15035)
  Use patched Gradle version (#15034)
  Add OpenAlex-based Citation Fetcher (#15023)
  Update null annotaitons at EntryBasedFetcher (#15024)
  Fix CHANGELOG.md test
  Use _ for unused variables (#15028)
  Use ubuntu-latest for checkstyle and javadoc
  Update Gradle Wrapper from 9.3.0-jabref-2 to 9.3.1 (#15021)
  Use "ubuntu-slim" for most workflows (#15019)
  Refine GroupsTree (#15013)
Siedlerchr added a commit to Jalina2007/jabref that referenced this pull request Feb 5, 2026
…4902

* upstream/main: (23 commits)
  Some more recipes from OpenRewrite (JabRef#15030)
  feat: Add PDF Upload endpoint to EntryResource (JabRef#14963)
  Heuristics also used at batch (JabRef#15025)
  Fix cleanup-pr.yml
  New Crowdin updates (JabRef#15035)
  Use patched Gradle version (JabRef#15034)
  Add OpenAlex-based Citation Fetcher (JabRef#15023)
  Update null annotaitons at EntryBasedFetcher (JabRef#15024)
  Fix CHANGELOG.md test
  Use _ for unused variables (JabRef#15028)
  Use ubuntu-latest for checkstyle and javadoc
  Update Gradle Wrapper from 9.3.0-jabref-2 to 9.3.1 (JabRef#15021)
  Use "ubuntu-slim" for most workflows (JabRef#15019)
  Refine GroupsTree (JabRef#15013)
  New Crowdin updates (JabRef#15018)
  Added Clear group option (JabRef#15017)
  Chore(deps): Bump com.uber.nullaway:nullaway from 0.12.15 to 0.13.1 in /versions (JabRef#15006)
  Chore(deps): Bump tools.jackson:jackson-bom in /versions (JabRef#15007)
  No rush in Docker building
  Yaml issue workaround
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev: code-quality Issues related to code or architecture decisions Review effort 2/5 status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants