Skip to content

Add 'All' citation fetcher that aggregates results from all providers#15292

Merged
Siedlerchr merged 15 commits into
JabRef:mainfrom
NishantDG-SST:issue-15029-clean
Mar 13, 2026
Merged

Add 'All' citation fetcher that aggregates results from all providers#15292
Siedlerchr merged 15 commits into
JabRef:mainfrom
NishantDG-SST:issue-15029-clean

Conversation

@NishantDG-SST

Copy link
Copy Markdown
Contributor

Related issues and pull requests

Closes #15029

PR Description

In this pr, I added the All citation fetcher dropdown that queries every available provider simultaneously.
In the citation relations tab of the entry editor, and the backend fetcher logic. Previously users had to manually switch between providers and compare results. With the All fetcher JabRef automatically unions the results from CrossRef, OpenAlex, OpenCitations, and SemanticScholar in one go.

Steps to test

  1. Open JabRef with the example library
Screenshot 2026-03-08 at 6 14 35 AM 2. Open any entry in the entry editor. 3. Navigate to the Citations tab. Screenshot 2026-03-08 at 6 17 13 AM 4. Verify "All" appears first in the provider dropdown and is selected by default. 5. Click refresh — results from all providers should appear, deduplicated Screenshot 2026-03-08 at 6 13 35 AM 6. Switch to a single provider (e.g. CrossRef) — verify it still works normally

Checklist

  • 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 added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • [/] I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository
Screenshot 2026-03-08 at 5 56 05 AM

…rom all providers

- Implements CitationFetcher as AllCitationFetcher aggregating CrossRef,
  OpenAlex, OpenCitations, and SemanticScholar
- Deduplicates results using DuplicateCheck with BibDatabaseMode.BIBTEX
- Returns maximum citation count across all providers
- Tolerates individual provider failures gracefully
- Adds ALL entry to CitationFetcherType enum and factory method
- Covers behaviour with unit tests (failure tolerance, deduplication, max count)

Closes JabRef#15029
- Add ALL as first entry in CitationFetcherType enum
- Implement AllCitationFetcher aggregating CrossRef, OpenAlex,
  OpenCitations, and SemanticScholar
- Union results using DatabaseMerger with keyword separator from
  ImportFormatPreferences, as specified in the task
- Return maximum citation count across all providers
- Tolerate individual provider failures gracefully
- Fix race condition in SearchCitationsRelationsService by marking
  citationFetcher and citationCountFetcher fields as volatile
- Set ALL as the default citation fetcher in preferences
- Add unit tests covering failure tolerance, deduplication, and
  max citation count

Closes JabRef#15029
Copilot AI review requested due to automatic review settings March 8, 2026 01:02
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add "All" citation fetcher aggregating results from all providers

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add "All" citation fetcher aggregating results from all providers
• Implement AllCitationFetcher merging CrossRef, OpenAlex, OpenCitations, SemanticScholar
• Deduplicate results and return maximum citation count across providers
• Set "All" as default citation fetcher in preferences
• Add unit tests for failure tolerance, deduplication, max count
Diagram
flowchart LR
  A["Citation Fetcher Selection"] --> B["AllCitationFetcher"]
  B --> C["CrossRef"]
  B --> D["OpenAlex"]
  B --> E["OpenCitations"]
  B --> F["SemanticScholar"]
  C --> G["DatabaseMerger"]
  D --> G
  E --> G
  F --> G
  G --> H["Deduplicated Results"]
  H --> I["Max Citation Count"]
Loading

Grey Divider

File Changes

1. jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java ✨ Enhancement +117/-0

New AllCitationFetcher aggregating all providers

• New class implementing CitationFetcher interface for aggregating results from all providers
• Initializes list of four citation fetchers (CrossRef, OpenAlex, OpenCitations, SemanticScholar)
• Implements getReferences and getCitations methods using DatabaseMerger for deduplication
• Implements getCitationCount returning maximum count across all providers
• Gracefully handles individual provider failures with logging

jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java


2. jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/CitationFetcherType.java ✨ Enhancement +22/-8

Add ALL enum and factory support

• Add ALL enum entry as first option in CitationFetcherType
• Add factory method case for AllCitationFetcher instantiation
• Reformat getCitationFetcher method signature for readability

jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/CitationFetcherType.java


3. jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java 🧪 Tests +72/-0

Unit tests for AllCitationFetcher behavior

• New test class with three test cases covering AllCitationFetcher behavior
• Test toleratesProviderFailure verifies graceful handling of fetcher exceptions
• Test removesDuplicateEntries verifies deduplication of results
• Test returnsMaximumCitationCount verifies max count selection across providers

jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java


View more (4)
4. jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java ⚙️ Configuration changes +1/-1

Set ALL as default citation fetcher

• Change default citation fetcher type from SEMANTIC_SCHOLAR to ALL

jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java


5. jabgui/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java ⚙️ Configuration changes +1/-1

Update default citation fetcher preference

• Update default preference for CITATION_FETCHER_TYPE from SEMANTIC_SCHOLAR to ALL

jabgui/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java


6. jablib/src/main/java/org/jabref/logic/citation/SearchCitationsRelationsService.java 🐞 Bug fix +2/-2

Fix race condition with volatile fields

• Mark citationFetcher field as volatile to fix race condition
• Mark citationCountFetcher field as volatile to fix race condition

jablib/src/main/java/org/jabref/logic/citation/SearchCitationsRelationsService.java


7. CHANGELOG.md 📝 Documentation +1/-0

Document All citation fetcher feature

• Add entry documenting new "All" citation fetcher option
• Describe merging of results from all four providers with deduplication

CHANGELOG.md


Grey Divider

Qodo Logo

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

qodo-free-for-open-source-projects Bot commented Mar 8, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (4) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Changelog entry lacks issue link📘 Rule violation ✓ Correctness
Description
The new CHANGELOG entry has no issue reference and contains slightly unpolished wording (missing
article and inconsistent provider name). This reduces traceability and professionalism of
user-facing release notes.
Code

CHANGELOG.md[16]

+- We added "All" option to the citation fetcher combo box, which queries all providers (CrossRef, OpenAlex, OpenCitations, SemanticScholar) and merges the results into a single deduplicated list.
Evidence
Compliance requires user-facing text (including changelog entries) to be professional/typo-free and
to include required issue references when expected; the added entry at line 16 lacks an issue link
and uses imprecise wording.

CHANGELOG.md[16-16]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The added CHANGELOG.md entry is user-facing text but is missing an issue reference and has minor grammar/wording issues.
## Issue Context
Other entries in the same section include an issue link (e.g., `[#15134](...)`). The added entry should follow the same traceability and wording quality.
## Fix Focus Areas
- CHANGELOG.md[16-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Failures hidden as empty results🐞 Bug ⛯ Reliability
Description
AllCitationFetcher catches FetcherException per-provider and always returns a (possibly empty) list,
so a total outage/network failure becomes “No articles found” instead of an error. Worse, this can
still update the citation-relations insertion timestamp, preventing automatic refetch for the TTL
and leaving stale cached relations with no user-visible failure.
Code

jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[R94-111]

+    private List<BibEntry> fetch(FetchOperation operation) {
+        BibDatabase target = new BibDatabase();
+        DatabaseMerger merger = new DatabaseMerger(keywordSeparator);
+
+        for (CitationFetcher fetcher : fetchers) {
+            try {
+                List<BibEntry> results = operation.fetch(fetcher);
+                BibDatabase other = new BibDatabase();
+                other.insertEntries(results);
+                merger.merge(target, other);
+            } catch (FetcherException e) {
+                LOGGER.debug("Fetching from {} failed — continuing",
+                        fetcher.getName(), e);
+            }
+        }
+
+        return new ArrayList<>(target.getEntries());
+    }
Evidence
AllCitationFetcher swallows provider exceptions and returns whatever is in the target DB (possibly
empty). SearchCitationsRelationsService treats the returned list as a successful fetch and writes it
to the relations repository. The MVStore repository always updates the insertion timestamp even if
the fetched list is empty, which can make the store appear “fresh” even when the fetch actually
failed; the UI only shows an error when an exception bubbles up, otherwise an empty list is shown as
“No articles found.”

jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[94-111]
jablib/src/main/java/org/jabref/logic/citation/SearchCitationsRelationsService.java[102-115]
jablib/src/main/java/org/jabref/logic/citation/repository/MVStoreBibEntryRelationRepository.java[83-95]
jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java[799-821]
jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java[863-866]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`AllCitationFetcher` currently catches `FetcherException` for each provider and always returns a list. When *all* providers fail, callers get an empty list that is treated as a successful fetch: the UI shows “No articles found” and the relations cache timestamp may be updated, suppressing automatic refreshes and leaving stale data without any visible error.
### Issue Context
- `SearchCitationsRelationsService` writes whatever list it gets into the repository and relies on exceptions to represent failures.
- The MVStore-backed repository always updates the insertion timestamp even when the fetched list is empty.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[78-111]
- jablib/src/main/java/org/jabref/logic/citation/SearchCitationsRelationsService.java[102-137]
- jablib/src/main/java/org/jabref/logic/citation/repository/MVStoreBibEntryRelationRepository.java[83-125]
### Implementation notes (suggested)
- In `fetch(...)`, track `anySuccess` and collect caught exceptions.
- If `anySuccess == false` and at least one exception was caught, throw a new `FetcherException(&amp;amp;quot;All citation providers failed&amp;amp;quot;, lastException)`.
- Otherwise, return merged results.
- Consider emitting a *warning* (or surfaced notification, if appropriate) when some providers fail but others succeed.
- Update `getCitationCount` to `throws FetcherException` (matching the interface) and throw when all providers failed (or when no provider succeeded and exceptions occurred), instead of silently returning `Optional.empty()`.
- Add/adjust unit tests to cover “all providers fail =&amp;amp;gt; exception thrown” and “partial failure =&amp;amp;gt; still returns partial results”.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. All fetcher not localized 📘 Rule violation ✓ Correctness
Description
The new provider label All is introduced as a hardcoded Java string that is displayed in the UI
provider dropdown. This violates the requirement that user-facing text be localized.
Code

jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[28]

+    public static final String FETCHER_NAME = "All";
Evidence
The checklist requires localization for user-facing text in Java; the new UI-visible fetcher name is
hardcoded as "All" and then surfaced via
CitationFetcherType.ALL(AllCitationFetcher.FETCHER_NAME).

AGENTS.md
jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[28-28]
jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/CitationFetcherType.java[14-14]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new citation fetcher option label `All` is hardcoded and shown to users in the citation fetcher dropdown, but user-facing strings must be localized.
## Issue Context
`CitationRelationsTab` renders the dropdown using `CitationFetcherType::getName`, so the `FETCHER_NAME` text becomes UI-visible.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[28-28]
- jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/CitationFetcherType.java[14-18]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Optional asserted via get()📘 Rule violation ✓ Correctness
Description
The new test asserts Optional presence via isPresent() and then calls get(), which is a
discouraged Optional usage and makes assertions less direct. Use an equality assertion against the
expected Optional value instead.
Code

jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java[R69-70]

+        assertTrue(result.isPresent());
+        assertEquals(20, result.get());
Evidence
The checklist prefers content assertions over boolean checks and discourages
Optional.isPresent()/get() patterns when clearer alternatives exist; the new test uses both.

AGENTS.md
AGENTS.md
jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java[69-70]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test uses `assertTrue(result.isPresent())` followed by `result.get()`, which is less direct and relies on unsafe access patterns.
## Issue Context
JUnit assertions should prefer direct value/content comparisons, and Optional usage should avoid `isPresent()`/`get()` when an equality assertion is clearer.
## Fix Focus Areas
- jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java[61-71]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Sequential aggregation latency🐞 Bug ➹ Performance
Description
AllCitationFetcher queries providers in a simple for-loop; overall latency becomes roughly the sum
of provider latencies, which can make the citations tab refresh noticeably slower when “All” is
selected.
Code

jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[R98-108]

+        for (CitationFetcher fetcher : fetchers) {
+            try {
+                List<BibEntry> results = operation.fetch(fetcher);
+                BibDatabase other = new BibDatabase();
+                other.insertEntries(results);
+                merger.merge(target, other);
+            } catch (FetcherException e) {
+                LOGGER.debug("Fetching from {} failed — continuing",
+                        fetcher.getName(), e);
+            }
+        }
Evidence
The implementation iterates through each provider and performs the network fetch one-by-one; there
is no parallelism or early return for slow providers.

jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[98-108]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
“All” fetcher currently runs providers sequentially, increasing end-to-end latency.
### Issue Context
Each provider fetch is typically a network operation. Sequential calls can make refresh time significantly longer.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java[94-111]
### Implementation notes (suggested)
- Execute `operation.fetch(fetcher)` calls concurrently using a bounded executor (to avoid unbounded thread creation).
- Collect successful results and failures; merge successful results deterministically.
- Preserve the failure behavior: if *all* futures complete exceptionally, throw a `FetcherException`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

6. Test uses fetcher1 names📘 Rule violation ✓ Correctness
Description
The new test uses incremental variable names (fetcher1, fetcher2) that do not communicate intent
(e.g., failing vs succeeding fetcher). This reduces readability and can make future test maintenance
harder.
Code

jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java[R20-31]

+    private CitationFetcher fetcher1;
+    private CitationFetcher fetcher2;
+    private AllCitationFetcher allFetcher;
+
+    @BeforeEach
+    void setUp() {
+        fetcher1 = mock(CitationFetcher.class);
+        fetcher2 = mock(CitationFetcher.class);
+        when(fetcher1.getName()).thenReturn("MockFetcher1");
+        when(fetcher2.getName()).thenReturn("MockFetcher2");
+        allFetcher = new AllCitationFetcher(List.of(fetcher1, fetcher2));
+    }
Evidence
The checklist requires clear, meaningful names; the added test variables are numbered placeholders
rather than intent-revealing identifiers.

AGENTS.md
jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java[20-31]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Numbered variable names in tests (`fetcher1`, `fetcher2`) are not intent-revealing and reduce readability.
## Issue Context
These mocks represent different roles in the test scenarios (e.g., failing vs successful provider).
## Fix Focus Areas
- jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java[20-55]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@github-actions github-actions Bot added the good second issue Issues that involve a tour of two or three interweaved components in JabRef label Mar 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “All” citation fetcher option so the citation relations UI can query multiple citation providers and present a single deduplicated result set, addressing the “search all / union results” request from #15029.

Changes:

  • Introduce AllCitationFetcher and wire it into CitationFetcherType (including setting it as the default fetcher type).
  • Aggregate and deduplicate results across providers when “All” is selected.
  • Add unit tests for failure-tolerance, deduplication, and citation-count aggregation.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java New aggregator fetcher that queries multiple providers and merges/deduplicates results.
jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/CitationFetcherType.java Adds ALL enum value and factory wiring to construct AllCitationFetcher.
jablib/src/main/java/org/jabref/logic/citation/SearchCitationsRelationsService.java Makes fetcher fields volatile to improve cross-thread visibility when preferences change.
jabgui/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java Changes default citation fetcher preference to ALL.
jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java Changes default citation fetcher preference to ALL.
jablib/src/test/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcherTest.java New tests covering provider failure handling, deduplication, and max citation-count selection.
CHANGELOG.md Documents the new “All” citation fetcher option.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +94 to +107
private List<BibEntry> fetch(FetchOperation operation) {
BibDatabase target = new BibDatabase();
DatabaseMerger merger = new DatabaseMerger(keywordSeparator);

for (CitationFetcher fetcher : fetchers) {
try {
List<BibEntry> results = operation.fetch(fetcher);
BibDatabase other = new BibDatabase();
other.insertEntries(results);
merger.merge(target, other);
} catch (FetcherException e) {
LOGGER.debug("Fetching from {} failed — continuing",
fetcher.getName(), e);
}

Copilot AI Mar 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetch(...) swallows FetcherException from every provider and always returns the (possibly empty) merged list. If all providers fail, callers cannot distinguish “no citations found” from “network/API failure”, and (e.g., on refresh) this can overwrite previously cached relations with an empty result. Consider tracking whether at least one provider completed successfully; if none did, rethrow/aggregate the last FetcherException instead of returning an empty list.

Copilot uses AI. Check for mistakes.
Comment on lines +98 to +108
for (CitationFetcher fetcher : fetchers) {
try {
List<BibEntry> results = operation.fetch(fetcher);
BibDatabase other = new BibDatabase();
other.insertEntries(results);
merger.merge(target, other);
} catch (FetcherException e) {
LOGGER.debug("Fetching from {} failed — continuing",
fetcher.getName(), e);
}
}

Copilot AI Mar 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fetching providers is currently done sequentially. With multiple network-backed providers this can significantly increase refresh latency compared to querying in parallel (there is already precedent for parallel aggregation in CompositeSearchBasedFetcher). Consider running provider fetches concurrently (e.g., parallelStream/CompletableFuture) and then merging/deduplicating the combined results, while still handling per-provider failures.

Copilot uses AI. Check for mistakes.
Comment thread CHANGELOG.md
Comment thread CHANGELOG.md
- Build provider list from CitationFetcherType enum (excluding ALL)
  to avoid duplicate list that can drift when new providers are added
- Track anySuccess in fetch() and getCitationCount(); throw
  FetcherException when all providers fail instead of silently
  returning empty results
- Emit WARN log when some providers fail but others succeed
- Rename test variables to intent-revealing names
- Fix citation count assertion to use assertEquals(Optional.of(20))
- Add tests for all-providers-fail and partial-failure scenarios

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +44 to +54
for (CitationFetcherType type : CitationFetcherType.values()) {
if (type == CitationFetcherType.ALL) {
continue;
}
providers.add(type.buildCitationFetcher(
importerPreferences,
importFormatPreferences,
citationKeyPatternPreferences,
grobidPreferences,
aiService));
}

Copilot AI Mar 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CitationFetcherType does not define buildCitationFetcher(...), so this call will not compile. Use CitationFetcherType.getCitationFetcher(type, ...) (skipping ALL as you already do), or add an instance method on the enum (e.g., buildCitationFetcher delegating to the switch) and call that consistently.

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +113
private List<BibEntry> fetch(FetchOperation operation) {
BibDatabase target = new BibDatabase();
DatabaseMerger merger = new DatabaseMerger(keywordSeparator);

for (CitationFetcher fetcher : fetchers) {
try {
List<BibEntry> results = operation.fetch(fetcher);
BibDatabase other = new BibDatabase();
other.insertEntries(results);
merger.merge(target, other);
} catch (FetcherException e) {
LOGGER.debug("Fetching from {} failed — continuing",
fetcher.getName(), e);
}
}

return new ArrayList<>(target.getEntries());
}

Copilot AI Mar 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation swallows FetcherExceptions for each provider and returns an (possibly empty) merged list. If all providers fail, callers cannot distinguish a real “no results” from a total fetch failure; in particular SearchCitationsRelationsService will still write an updated timestamp to the relations store, which can prevent retries until TTL expires. Consider tracking whether at least one provider succeeded; if none succeeded, rethrow (or throw) a FetcherException so the failure is surfaced and the cache timestamp is not advanced.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +16
import org.jabref.logic.importer.fetcher.OpenAlex;
import org.jabref.logic.importer.fetcher.citation.crossref.CrossRefCitationFetcher;
import org.jabref.logic.importer.fetcher.citation.opencitations.OpenCitationsFetcher;
import org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarCitationFetcher;

Copilot AI Mar 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several unused imports (e.g., OpenAlex, CrossRefCitationFetcher, OpenCitationsFetcher, SemanticScholarCitationFetcher). These are likely to fail formatting/static-analysis checks; please remove unused imports.

Suggested change
import org.jabref.logic.importer.fetcher.OpenAlex;
import org.jabref.logic.importer.fetcher.citation.crossref.CrossRefCitationFetcher;
import org.jabref.logic.importer.fetcher.citation.opencitations.OpenCitationsFetcher;
import org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarCitationFetcher;

Copilot uses AI. Check for mistakes.
Comment on lines +100 to +110
for (CitationFetcher fetcher : fetchers) {
try {
List<BibEntry> results = operation.fetch(fetcher);
BibDatabase other = new BibDatabase();
other.insertEntries(results);
merger.merge(target, other);
} catch (FetcherException e) {
LOGGER.debug("Fetching from {} failed — continuing",
fetcher.getName(), e);
}
}

Copilot AI Mar 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fetch loop runs providers sequentially, not “simultaneously” as stated in the PR description/steps. Either adjust the description, or execute provider fetches concurrently (while still merging/deduplicating deterministically).

Copilot uses AI. Check for mistakes.
@testlens-app

This comment has been minimized.

@testlens-app

This comment has been minimized.

@testlens-app

This comment has been minimized.

@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 8, 2026
Comment on lines +36 to +37
private volatile CitationFetcher citationFetcher;
private volatile CitationCountFetcher citationCountFetcher;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do these need to be volatile?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So when the user switches between the citations the JMM does not guarantee the worker thread will see the updated value immediately it may read a stale cached copy from its local CPU cache. This means a user could switch to "All" in the dropdown but the background task could still be using the old fetcher (e.g. CrossRef) causing unexpected errors.
So Adding volatile forces all reads to go directly to main memory ensuring the worker thread always sees the latest value written by the JavaFX thread.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test this? We are not in a highly parallel system.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When switching to "All" in the dropdown CrossRef HTTP 429 errors were still appearing in the UI even though "All" was selected. So i added the "volatile" keyword to ensure the worker thread always sees the updated fetcher after the switch happy to revert it if you think this is unnecessary.

super();

defaults.put(ENTRY_EDITOR_PREVIEW_DIVIDER_POS, 0.5);
defaults.put(CITATION_FETCHER_TYPE, CitationFetcherType.SEMANTIC_SCHOLAR.name());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"ALL" will cause high load. We should leave this setting untouched.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok i have reverted default citation fetcher to SEMANTIC_SCHOLAR

@testlens-app

This comment has been minimized.

}

// Test constructor
AllCitationFetcher(List<CitationFetcher> fetchers) {

@Siedlerchr Siedlerchr Mar 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adapt the test to use the real constructur, just use mocks. This ensures that you are testing the constructor logic as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Removed the test constructor and rewrote the tests to use the real constructor, following the same pattern as CrossRefCitationFetcherTest, OpenAlexCitationFetcherTest .

@Siedlerchr

Copy link
Copy Markdown
Member

overall okay, just adapt the test to use the normal constructor

@testlens-app

This comment has been minimized.

max = max.isEmpty() ? count : Optional.of(Math.max(max.get(), count.get()));
}
} catch (FetcherException e) {
} catch (Exception e) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only catch FetcherException! Did your AI tool change this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, i ran the AllCitationFetcherTest with "10.47397/tb/44-3/tb138kopp-jabref" from CrossRefCitationFetcherTest but it gave a RuntimeException which the FetcherException couldnt catch so i changed to catch Exception

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will revert back to FetcherException then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have the full stacktrace?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In SemanticScholarCitationFetcher

SemanticScholarCitationFetcher.getReferences():

ifPresent(Unchecked.consumer(disclaimer -> {
throw new FetcherException(...);
}));

here its throwing a UncheckedException error so this gave a build failure as it wasnt caught by FetcherException ,

So i either have to catch (FetcherException e) and catch (RuntimeException e) both OR catch(Exception e)

@NishantDG-SST NishantDG-SST Mar 9, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have the full stacktrace?

org.jooq.lambda.UncheckedException: org.jabref.logic.importer.FetcherException: Restricted access to references: Notice: The following paper fields have been elided by the publisher: {'references'}. Paper or abstract available at https://api.unpaywall.org/v2/10.47397/tb/44-3/tb138kopp-jabref?email=<INSERT_YOUR_EMAIL> or https://doi.org/10.47397/tb/44-3/tb138kopp-jabref, which is subject to the license by the author or copyright owner provided with this content. Please go to the source to verify the license and copyright information for your use.
	at org.jooq.lambda.Unchecked.lambda$static$0(Unchecked.java:61)
	at org.jooq.lambda.Unchecked.lambda$consumer$17(Unchecked.java:697)
	at java.base/java.util.Optional.ifPresent(Optional.java:178)
	at org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarCitationFetcher.getReferences(SemanticScholarCitationFetcher.java:111)
	at org.jabref.logic.importer.fetcher.citation.AllCitationFetcher.lambda$getReferences$0(AllCitationFetcher.java:50)
	at org.jabref.logic.importer.fetcher.citation.AllCitationFetcher.fetch(AllCitationFetcher.java:92)
	at org.jabref.logic.importer.fetcher.citation.AllCitationFetcher.getReferences(AllCitationFetcher.java:50)
	at org.jabref.logic.importer.fetcher.citation.AllCitationFetcherTest.getReferences(AllCitationFetcherTest.java:38)
Caused by: org.jabref.logic.importer.FetcherException: Restricted access to references: Notice: The following paper fields have been elided by the publisher: {'references'}. Paper or abstract available at https://api.unpaywall.org/v2/10.47397/tb/44-3/tb138kopp-jabref?email=<INSERT_YOUR_EMAIL> or https://doi.org/10.47397/tb/44-3/tb138kopp-jabref, which is subject to the license by the author or copyright owner provided with this content. Please go to the source to verify the license and copyright information for your use.
	at org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarCitationFetcher.lambda$getReferences$3(SemanticScholarCitationFetcher.java:114)
	at org.jooq.lambda.Unchecked.lambda$consumer$17(Unchecked.java:694)
	... 6 more
Cause 1: org.jabref.logic.importer.FetcherException: Restricted access to references: Notice: The following paper fields have been elided by the publisher: {'references'}. Paper or abstract available at https://api.unpaywall.org/v2/10.47397/tb/44-3/tb138kopp-jabref?email=<INSERT_YOUR_EMAIL> or https://doi.org/10.47397/tb/44-3/tb138kopp-jabref, which is subject to the license by the author or copyright owner provided with this content. Please go to the source to verify the license and copyright information for your use.
	at app//org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarCitationFetcher.lambda$getReferences$3(SemanticScholarCitationFetcher.java:114)
	at app//org.jooq.lambda.Unchecked.lambda$consumer$17(Unchecked.java:694)
	at java.base@25.0.2/java.util.Optional.ifPresent(Optional.java:178)
	at app//org.jabref.logic.importer.fetcher.citation.semanticscholar.SemanticScholarCitationFetcher.getReferences(SemanticScholarCitationFetcher.java:111)
	at app//org.jabref.logic.importer.fetcher.citation.AllCitationFetcher.lambda$getReferences$0(AllCitationFetcher.java:50)
	at app//org.jabref.logic.importer.fetcher.citation.AllCitationFetcher.fetch(AllCitationFetcher.java:92)
	at app//org.jabref.logic.importer.fetcher.citation.AllCitationFetcher.getReferences(AllCitationFetcher.java:50)
	at app//org.jabref.logic.importer.fetcher.citation.AllCitationFetcherTest.getReferences(AllCitationFetcherTest.java:38)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the hint! I refactored this so that only a FetcherException is now thrown

}

@Test
void removesDuplicateEntries() throws Exception {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep the test cases

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can tes them independently

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I restore the test constructor to inject mock fetchers for these tests and keeping the real constructor tests separate?

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Mar 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

@testlens-app

This comment has been minimized.

@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 13, 2026
@testlens-app

testlens-app Bot commented Mar 13, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 3c9a984
▶️ Tests: 10135 executed
⚪️ Checks: 55/55 completed


Learn more about TestLens at testlens.app.

@Siedlerchr Siedlerchr enabled auto-merge March 13, 2026 20:06
@Siedlerchr Siedlerchr added this pull request to the merge queue Mar 13, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Mar 13, 2026
Merged via the queue into JabRef:main with commit 1d81093 Mar 13, 2026
55 checks passed
Syimyk43 pushed a commit to Syimyk43/jabref that referenced this pull request Mar 15, 2026
…JabRef#15292)

* Add 'All' citation fetcher that aggregates and deduplicates results from all providers

- Implements CitationFetcher as AllCitationFetcher aggregating CrossRef,
  OpenAlex, OpenCitations, and SemanticScholar
- Deduplicates results using DuplicateCheck with BibDatabaseMode.BIBTEX
- Returns maximum citation count across all providers
- Tolerates individual provider failures gracefully
- Adds ALL entry to CitationFetcherType enum and factory method
- Covers behaviour with unit tests (failure tolerance, deduplication, max count)

Closes JabRef#15029

* Add 'All' citation fetcher that aggregates results from all providers

- Add ALL as first entry in CitationFetcherType enum
- Implement AllCitationFetcher aggregating CrossRef, OpenAlex,
  OpenCitations, and SemanticScholar
- Union results using DatabaseMerger with keyword separator from
  ImportFormatPreferences, as specified in the task
- Return maximum citation count across all providers
- Tolerate individual provider failures gracefully
- Fix race condition in SearchCitationsRelationsService by marking
  citationFetcher and citationCountFetcher fields as volatile
- Set ALL as the default citation fetcher in preferences
- Add unit tests covering failure tolerance, deduplication, and
  max citation count

Closes JabRef#15029

* Update CHANGELOG for issue JabRef#15029

* Address bot review: fix AllCitationFetcher and improve tests

- Build provider list from CitationFetcherType enum (excluding ALL)
  to avoid duplicate list that can drift when new providers are added
- Track anySuccess in fetch() and getCitationCount(); throw
  FetcherException when all providers fail instead of silently
  returning empty results
- Emit WARN log when some providers fail but others succeed
- Rename test variables to intent-revealing names
- Fix citation count assertion to use assertEquals(Optional.of(20))
- Add tests for all-providers-fail and partial-failure scenarios

* Trigger CI

* Reformat AllCitationFetcher

* Fix checkstyle: remove blank line at start of constructor block

* Reverted back to semantic scholar ui preference

* Revert default citation fetcher to SEMANTIC_SCHOLAR in EntryEditorPreferences

* Re-trigger CI

* Adapt tests to use real constructor with mocks, remove test constructor

* fix unchecked excpetion

---------

Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>
github-merge-queue Bot pushed a commit that referenced this pull request Mar 15, 2026
* Close entry editor when last library is closed

When no library tab is active, the entry editor remained visible.
Added close() call in the activeTabProperty listener's else branch
to handle the zero-libraries-open case.

Fixes #13125

* Update CHANGELOG for #13125

* Fix case-insensitive DOI comparison in duplicate detection (#12967)

* Chore(deps): Bump org.gradlex:java-module-dependencies in /build-logic (#15328)

Bumps [org.gradlex:java-module-dependencies](https://github.com/gradlex-org/java-module-dependencies) from 1.12 to 1.12.1.
- [Release notes](https://github.com/gradlex-org/java-module-dependencies/releases)
- [Changelog](https://github.com/gradlex-org/java-module-dependencies/blob/main/CHANGELOG.md)
- [Commits](gradlex-org/java-module-dependencies@v1.12...v1.12.1)

---
updated-dependencies:
- dependency-name: org.gradlex:java-module-dependencies
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.openrewrite.rewrite from 7.26.0 to 7.28.1 (#15326)

Bumps org.openrewrite.rewrite from 7.26.0 to 7.28.1.

---
updated-dependencies:
- dependency-name: org.openrewrite.rewrite
  dependency-version: 7.28.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.mockito:mockito-core in /versions (#15330)

Bumps [org.mockito:mockito-core](https://github.com/mockito/mockito) from 5.22.0 to 5.23.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](mockito/mockito@v5.22.0...v5.23.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-core
  dependency-version: 5.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.cyclonedx.bom from 3.2.0 to 3.2.1 (#15327)

Bumps org.cyclonedx.bom from 3.2.0 to 3.2.1.

---
updated-dependencies:
- dependency-name: org.cyclonedx.bom
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump com.squareup.okio:okio-jvm in /versions (#15329)

Bumps [com.squareup.okio:okio-jvm](https://github.com/square/okio) from 3.16.4 to 3.17.0.
- [Changelog](https://github.com/square/okio/blob/master/CHANGELOG.md)
- [Commits](square/okio@parent-3.16.4...parent-3.17.0)

---
updated-dependencies:
- dependency-name: com.squareup.okio:okio-jvm
  dependency-version: 3.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* New translations jabref_en.properties (Italian) (#15334)

* RIS export SP/EP fields when pages contain Unicode en-dash or em-dash (#15315)

* Extend the split regex to match en-dash and em-dash

* Added tests

---------

Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* Remove object redundancy, miscellaneous refactoring (#15332)

* Remove object redundancy, miscellaneous refactoring

Signed-off-by: subhramit <subhramit.bb@live.in>

* Use abbreviationRepository parameter

Signed-off-by: subhramit <subhramit.bb@live.in>

* Use less injections for journal abbreviations repository

Signed-off-by: subhramit <subhramit.bb@live.in>

* Indent

Signed-off-by: subhramit <subhramit.bb@live.in>

* Revert to codepoint

---------

Signed-off-by: subhramit <subhramit.bb@live.in>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* Add drag-and-drop support for Citation Relations tab (#15181)

* Add drag-and-drop support for Citation Relations tab

- Implement drag detection in CitationRelationsTab to allow dragging entries
- Add drag support to ViewModelListCellFactory
- Fix NullPointerException in FrameDndHandler when dropping onto tabs without IDs
- Fixes #15135

* Fix: correctly set drop completion status for entries

* Fix: Add Unreleased section and moved changelog entries

* Fix CHANGELOG formatting and upstream linter errors; removed empty groups

* Fix code consistency for cr

* Add explicit type

* Consistency in CHANGELOG.md

---------

Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>

* Update dependency org.eclipse.jgit:org.eclipse.jgit.pgm to v7.6.0.202603022253-r (#15335)

* Chore(deps): Bump org.cyclonedx.bom from 3.2.1 to 3.2.2 (#15337)

Bumps org.cyclonedx.bom from 3.2.1 to 3.2.2.

---
updated-dependencies:
- dependency-name: org.cyclonedx.bom
  dependency-version: 3.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.eclipse.jgit:org.eclipse.jgit in /versions (#15338)

Bumps [org.eclipse.jgit:org.eclipse.jgit](https://github.com/eclipse-jgit/jgit) from 7.5.0.202512021534-r to 7.6.0.202603022253-r.
- [Commits](eclipse-jgit/jgit@v7.5.0.202512021534-r...v7.6.0.202603022253-r)

---
updated-dependencies:
- dependency-name: org.eclipse.jgit:org.eclipse.jgit
  dependency-version: 7.6.0.202603022253-r
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add 'All' citation fetcher that aggregates results from all providers (#15292)

* Add 'All' citation fetcher that aggregates and deduplicates results from all providers

- Implements CitationFetcher as AllCitationFetcher aggregating CrossRef,
  OpenAlex, OpenCitations, and SemanticScholar
- Deduplicates results using DuplicateCheck with BibDatabaseMode.BIBTEX
- Returns maximum citation count across all providers
- Tolerates individual provider failures gracefully
- Adds ALL entry to CitationFetcherType enum and factory method
- Covers behaviour with unit tests (failure tolerance, deduplication, max count)

Closes #15029

* Add 'All' citation fetcher that aggregates results from all providers

- Add ALL as first entry in CitationFetcherType enum
- Implement AllCitationFetcher aggregating CrossRef, OpenAlex,
  OpenCitations, and SemanticScholar
- Union results using DatabaseMerger with keyword separator from
  ImportFormatPreferences, as specified in the task
- Return maximum citation count across all providers
- Tolerate individual provider failures gracefully
- Fix race condition in SearchCitationsRelationsService by marking
  citationFetcher and citationCountFetcher fields as volatile
- Set ALL as the default citation fetcher in preferences
- Add unit tests covering failure tolerance, deduplication, and
  max citation count

Closes #15029

* Update CHANGELOG for issue #15029

* Address bot review: fix AllCitationFetcher and improve tests

- Build provider list from CitationFetcherType enum (excluding ALL)
  to avoid duplicate list that can drift when new providers are added
- Track anySuccess in fetch() and getCitationCount(); throw
  FetcherException when all providers fail instead of silently
  returning empty results
- Emit WARN log when some providers fail but others succeed
- Rename test variables to intent-revealing names
- Fix citation count assertion to use assertEquals(Optional.of(20))
- Add tests for all-providers-fail and partial-failure scenarios

* Trigger CI

* Reformat AllCitationFetcher

* Fix checkstyle: remove blank line at start of constructor block

* Reverted back to semantic scholar ui preference

* Revert default citation fetcher to SEMANTIC_SCHOLAR in EntryEditorPreferences

* Re-trigger CI

* Adapt tests to use real constructor with mocks, remove test constructor

* fix unchecked excpetion

---------

Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>

* Avoid error logs when search queries are incomplete (#15333)

* Avoid error logs when search queries are incomplete

Log the parsing error at debug level instead of error level. This prevents having
unnecessary output when user is still entering input like "title =".

* Update changelog for fixing incomplete search logging issue

* Update changelog entry for incomplete search logging issue

* Refine changelog entry for incomplete search logging issue

* Chore(deps): Bump org.openrewrite.recipe:rewrite-recipe-bom from 3.24.0 to 3.25.0 (#15217)

* Chore(deps): Bump org.openrewrite.recipe:rewrite-recipe-bom

Bumps [org.openrewrite.recipe:rewrite-recipe-bom](https://github.com/openrewrite/rewrite-recipe-bom) from 3.24.0 to 3.25.0.
- [Release notes](https://github.com/openrewrite/rewrite-recipe-bom/releases)
- [Commits](openrewrite/rewrite-recipe-bom@v3.24.0...v3.25.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.recipe:rewrite-recipe-bom
  dependency-version: 3.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* udpate plugin

* update rewrite

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>

* Select better value in MultiMergeEntries dialog component (#15027) (#15255)

* Select better value in MultiMergeEntries dialog component (#15027)

* Use PlausibilityComparatorFactory in MultiMergeEntriesViewModel
to select the more plausible value when merging fields from
multiple sources, instead of always keeping the first-seen value.

* Add DateFieldPlausibilityComparator to prefer more specific dates.

* Add unit tests for DateFieldPlausibilityComparator

* implement review comments

* Fix trailing whitespace in MultiMergeEntriesViewModelTest

* Trigger CI

* CI: re-trigger

* CI: re-trigger

---------

Co-authored-by: Christoph <siedlerkiller@gmail.com>

* Fix reset and import for PreviewPreferences (#15306)

* Cleanups

* Refactor PreviewPreferences for resetting and import

* Some null checks and migrations

* Fix wrong notnull

* Fix import

* Avoid addAll crash on immutable List

* Add forgotten customPreviewLayout

* Fix artifact from code iteration

* Refactor for consistency

* Fix artifact from code iteration

* Enhance dummy fallback layout

* Try to fix jbang

* Apply IDE suggestions

* Fix weird checkstyle behaviour

* Add default styles

* Fix migration tests

* Add tests

* Small cleanups

---------

Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>

* Fix javadoc markdown artifacts (#15309)

* Closes #14897
This incorporates all the pending old Javadoc to  Markdown changes required after merging #14891.The following files are changed:
1.AutoCompletionTextInputBinding.java
2.JabRefCliPreferences.java
3.SearchBasedParserFetcher.java
4.StartNewStudyAction.java
                                             1.

* 1.

* Rsolved mix up of endregion and endRegion.Final one is endregion.
1.File changed-JabRefCliPreferences.java

* Rsolved format issue related to line space.Files changed.
1.JabRefCliPreferences.java
2.SearchBasedParserFetcher.java

* Files changed.
1.JabRefCliPreferences.java.
The following changes are done:-
1.Added // endregion to maintain sync with region:AI
  And // region Push to application preferences and //region to Git
2.Changed region: to region
3.Changed region: Cleanup to previous ToDo: Cleanup
4.changed endRegion to end region
5.Adjusted  dangling // endregion by merging Imported Preference tag(new one) with Other Preferences(old one)

* Files changed.
1.JabRefCliPreferences.java.
The following changes are done:-
1.Apply IntelliJ formatting

* Update CHANGELOG for JabRef#12967

* Apply case-insensitive comparison only to DOI identifiers

* Apply IntelliJ code formatting to DuplicateCheck and DuplicateCheckTest

* Add tests for case-insensitive DOI duplicate detection

* Fix case-insensitive DOI comparison in duplicate detection

* fix formatting

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: subhramit <subhramit.bb@live.in>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Faneesh Juneja <willowstration@gmail.com>
Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
Co-authored-by: Paul <thecoder777.github@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>
Co-authored-by: Mend Renovate <bot@renovateapp.com>
Co-authored-by: Nishant Dasgupta <nishant.24bcs10451@sst.scaler.com>
Co-authored-by: Mike Zhang <97817030+mikezhanghaozhe@users.noreply.github.com>
Co-authored-by: JunWang222 <70090336+JunWang222@users.noreply.github.com>
Co-authored-by: AbhijitBhowmick <94289124+AbhijitBhowmick@users.noreply.github.com>
AnvitaPrasad pushed a commit to AnvitaPrasad/jabref that referenced this pull request Mar 18, 2026
…JabRef#15292)

* Add 'All' citation fetcher that aggregates and deduplicates results from all providers

- Implements CitationFetcher as AllCitationFetcher aggregating CrossRef,
  OpenAlex, OpenCitations, and SemanticScholar
- Deduplicates results using DuplicateCheck with BibDatabaseMode.BIBTEX
- Returns maximum citation count across all providers
- Tolerates individual provider failures gracefully
- Adds ALL entry to CitationFetcherType enum and factory method
- Covers behaviour with unit tests (failure tolerance, deduplication, max count)

Closes JabRef#15029

* Add 'All' citation fetcher that aggregates results from all providers

- Add ALL as first entry in CitationFetcherType enum
- Implement AllCitationFetcher aggregating CrossRef, OpenAlex,
  OpenCitations, and SemanticScholar
- Union results using DatabaseMerger with keyword separator from
  ImportFormatPreferences, as specified in the task
- Return maximum citation count across all providers
- Tolerate individual provider failures gracefully
- Fix race condition in SearchCitationsRelationsService by marking
  citationFetcher and citationCountFetcher fields as volatile
- Set ALL as the default citation fetcher in preferences
- Add unit tests covering failure tolerance, deduplication, and
  max citation count

Closes JabRef#15029

* Update CHANGELOG for issue JabRef#15029

* Address bot review: fix AllCitationFetcher and improve tests

- Build provider list from CitationFetcherType enum (excluding ALL)
  to avoid duplicate list that can drift when new providers are added
- Track anySuccess in fetch() and getCitationCount(); throw
  FetcherException when all providers fail instead of silently
  returning empty results
- Emit WARN log when some providers fail but others succeed
- Rename test variables to intent-revealing names
- Fix citation count assertion to use assertEquals(Optional.of(20))
- Add tests for all-providers-fail and partial-failure scenarios

* Trigger CI

* Reformat AllCitationFetcher

* Fix checkstyle: remove blank line at start of constructor block

* Reverted back to semantic scholar ui preference

* Revert default citation fetcher to SEMANTIC_SCHOLAR in EntryEditorPreferences

* Re-trigger CI

* Adapt tests to use real constructor with mocks, remove test constructor

* fix unchecked excpetion

---------

Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>
AnvitaPrasad pushed a commit to AnvitaPrasad/jabref that referenced this pull request Mar 18, 2026
* Close entry editor when last library is closed

When no library tab is active, the entry editor remained visible.
Added close() call in the activeTabProperty listener's else branch
to handle the zero-libraries-open case.

Fixes JabRef#13125

* Update CHANGELOG for JabRef#13125

* Fix case-insensitive DOI comparison in duplicate detection (JabRef#12967)

* Chore(deps): Bump org.gradlex:java-module-dependencies in /build-logic (JabRef#15328)

Bumps [org.gradlex:java-module-dependencies](https://github.com/gradlex-org/java-module-dependencies) from 1.12 to 1.12.1.
- [Release notes](https://github.com/gradlex-org/java-module-dependencies/releases)
- [Changelog](https://github.com/gradlex-org/java-module-dependencies/blob/main/CHANGELOG.md)
- [Commits](gradlex-org/java-module-dependencies@v1.12...v1.12.1)

---
updated-dependencies:
- dependency-name: org.gradlex:java-module-dependencies
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.openrewrite.rewrite from 7.26.0 to 7.28.1 (JabRef#15326)

Bumps org.openrewrite.rewrite from 7.26.0 to 7.28.1.

---
updated-dependencies:
- dependency-name: org.openrewrite.rewrite
  dependency-version: 7.28.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.mockito:mockito-core in /versions (JabRef#15330)

Bumps [org.mockito:mockito-core](https://github.com/mockito/mockito) from 5.22.0 to 5.23.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](mockito/mockito@v5.22.0...v5.23.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-core
  dependency-version: 5.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.cyclonedx.bom from 3.2.0 to 3.2.1 (JabRef#15327)

Bumps org.cyclonedx.bom from 3.2.0 to 3.2.1.

---
updated-dependencies:
- dependency-name: org.cyclonedx.bom
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump com.squareup.okio:okio-jvm in /versions (JabRef#15329)

Bumps [com.squareup.okio:okio-jvm](https://github.com/square/okio) from 3.16.4 to 3.17.0.
- [Changelog](https://github.com/square/okio/blob/master/CHANGELOG.md)
- [Commits](square/okio@parent-3.16.4...parent-3.17.0)

---
updated-dependencies:
- dependency-name: com.squareup.okio:okio-jvm
  dependency-version: 3.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* New translations jabref_en.properties (Italian) (JabRef#15334)

* RIS export SP/EP fields when pages contain Unicode en-dash or em-dash (JabRef#15315)

* Extend the split regex to match en-dash and em-dash

* Added tests

---------

Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* Remove object redundancy, miscellaneous refactoring (JabRef#15332)

* Remove object redundancy, miscellaneous refactoring

Signed-off-by: subhramit <subhramit.bb@live.in>

* Use abbreviationRepository parameter

Signed-off-by: subhramit <subhramit.bb@live.in>

* Use less injections for journal abbreviations repository

Signed-off-by: subhramit <subhramit.bb@live.in>

* Indent

Signed-off-by: subhramit <subhramit.bb@live.in>

* Revert to codepoint

---------

Signed-off-by: subhramit <subhramit.bb@live.in>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* Add drag-and-drop support for Citation Relations tab (JabRef#15181)

* Add drag-and-drop support for Citation Relations tab

- Implement drag detection in CitationRelationsTab to allow dragging entries
- Add drag support to ViewModelListCellFactory
- Fix NullPointerException in FrameDndHandler when dropping onto tabs without IDs
- Fixes JabRef#15135

* Fix: correctly set drop completion status for entries

* Fix: Add Unreleased section and moved changelog entries

* Fix CHANGELOG formatting and upstream linter errors; removed empty groups

* Fix code consistency for cr

* Add explicit type

* Consistency in CHANGELOG.md

---------

Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>

* Update dependency org.eclipse.jgit:org.eclipse.jgit.pgm to v7.6.0.202603022253-r (JabRef#15335)

* Chore(deps): Bump org.cyclonedx.bom from 3.2.1 to 3.2.2 (JabRef#15337)

Bumps org.cyclonedx.bom from 3.2.1 to 3.2.2.

---
updated-dependencies:
- dependency-name: org.cyclonedx.bom
  dependency-version: 3.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.eclipse.jgit:org.eclipse.jgit in /versions (JabRef#15338)

Bumps [org.eclipse.jgit:org.eclipse.jgit](https://github.com/eclipse-jgit/jgit) from 7.5.0.202512021534-r to 7.6.0.202603022253-r.
- [Commits](eclipse-jgit/jgit@v7.5.0.202512021534-r...v7.6.0.202603022253-r)

---
updated-dependencies:
- dependency-name: org.eclipse.jgit:org.eclipse.jgit
  dependency-version: 7.6.0.202603022253-r
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add 'All' citation fetcher that aggregates results from all providers (JabRef#15292)

* Add 'All' citation fetcher that aggregates and deduplicates results from all providers

- Implements CitationFetcher as AllCitationFetcher aggregating CrossRef,
  OpenAlex, OpenCitations, and SemanticScholar
- Deduplicates results using DuplicateCheck with BibDatabaseMode.BIBTEX
- Returns maximum citation count across all providers
- Tolerates individual provider failures gracefully
- Adds ALL entry to CitationFetcherType enum and factory method
- Covers behaviour with unit tests (failure tolerance, deduplication, max count)

Closes JabRef#15029

* Add 'All' citation fetcher that aggregates results from all providers

- Add ALL as first entry in CitationFetcherType enum
- Implement AllCitationFetcher aggregating CrossRef, OpenAlex,
  OpenCitations, and SemanticScholar
- Union results using DatabaseMerger with keyword separator from
  ImportFormatPreferences, as specified in the task
- Return maximum citation count across all providers
- Tolerate individual provider failures gracefully
- Fix race condition in SearchCitationsRelationsService by marking
  citationFetcher and citationCountFetcher fields as volatile
- Set ALL as the default citation fetcher in preferences
- Add unit tests covering failure tolerance, deduplication, and
  max citation count

Closes JabRef#15029

* Update CHANGELOG for issue JabRef#15029

* Address bot review: fix AllCitationFetcher and improve tests

- Build provider list from CitationFetcherType enum (excluding ALL)
  to avoid duplicate list that can drift when new providers are added
- Track anySuccess in fetch() and getCitationCount(); throw
  FetcherException when all providers fail instead of silently
  returning empty results
- Emit WARN log when some providers fail but others succeed
- Rename test variables to intent-revealing names
- Fix citation count assertion to use assertEquals(Optional.of(20))
- Add tests for all-providers-fail and partial-failure scenarios

* Trigger CI

* Reformat AllCitationFetcher

* Fix checkstyle: remove blank line at start of constructor block

* Reverted back to semantic scholar ui preference

* Revert default citation fetcher to SEMANTIC_SCHOLAR in EntryEditorPreferences

* Re-trigger CI

* Adapt tests to use real constructor with mocks, remove test constructor

* fix unchecked excpetion

---------

Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>

* Avoid error logs when search queries are incomplete (JabRef#15333)

* Avoid error logs when search queries are incomplete

Log the parsing error at debug level instead of error level. This prevents having
unnecessary output when user is still entering input like "title =".

* Update changelog for fixing incomplete search logging issue

* Update changelog entry for incomplete search logging issue

* Refine changelog entry for incomplete search logging issue

* Chore(deps): Bump org.openrewrite.recipe:rewrite-recipe-bom from 3.24.0 to 3.25.0 (JabRef#15217)

* Chore(deps): Bump org.openrewrite.recipe:rewrite-recipe-bom

Bumps [org.openrewrite.recipe:rewrite-recipe-bom](https://github.com/openrewrite/rewrite-recipe-bom) from 3.24.0 to 3.25.0.
- [Release notes](https://github.com/openrewrite/rewrite-recipe-bom/releases)
- [Commits](openrewrite/rewrite-recipe-bom@v3.24.0...v3.25.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.recipe:rewrite-recipe-bom
  dependency-version: 3.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* udpate plugin

* update rewrite

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>

* Select better value in MultiMergeEntries dialog component (JabRef#15027) (JabRef#15255)

* Select better value in MultiMergeEntries dialog component (JabRef#15027)

* Use PlausibilityComparatorFactory in MultiMergeEntriesViewModel
to select the more plausible value when merging fields from
multiple sources, instead of always keeping the first-seen value.

* Add DateFieldPlausibilityComparator to prefer more specific dates.

* Add unit tests for DateFieldPlausibilityComparator

* implement review comments

* Fix trailing whitespace in MultiMergeEntriesViewModelTest

* Trigger CI

* CI: re-trigger

* CI: re-trigger

---------

Co-authored-by: Christoph <siedlerkiller@gmail.com>

* Fix reset and import for PreviewPreferences (JabRef#15306)

* Cleanups

* Refactor PreviewPreferences for resetting and import

* Some null checks and migrations

* Fix wrong notnull

* Fix import

* Avoid addAll crash on immutable List

* Add forgotten customPreviewLayout

* Fix artifact from code iteration

* Refactor for consistency

* Fix artifact from code iteration

* Enhance dummy fallback layout

* Try to fix jbang

* Apply IDE suggestions

* Fix weird checkstyle behaviour

* Add default styles

* Fix migration tests

* Add tests

* Small cleanups

---------

Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>

* Fix javadoc markdown artifacts (JabRef#15309)

* Closes JabRef#14897
This incorporates all the pending old Javadoc to  Markdown changes required after merging JabRef#14891.The following files are changed:
1.AutoCompletionTextInputBinding.java
2.JabRefCliPreferences.java
3.SearchBasedParserFetcher.java
4.StartNewStudyAction.java
                                             1.

* 1.

* Rsolved mix up of endregion and endRegion.Final one is endregion.
1.File changed-JabRefCliPreferences.java

* Rsolved format issue related to line space.Files changed.
1.JabRefCliPreferences.java
2.SearchBasedParserFetcher.java

* Files changed.
1.JabRefCliPreferences.java.
The following changes are done:-
1.Added // endregion to maintain sync with region:AI
  And // region Push to application preferences and //region to Git
2.Changed region: to region
3.Changed region: Cleanup to previous ToDo: Cleanup
4.changed endRegion to end region
5.Adjusted  dangling // endregion by merging Imported Preference tag(new one) with Other Preferences(old one)

* Files changed.
1.JabRefCliPreferences.java.
The following changes are done:-
1.Apply IntelliJ formatting

* Update CHANGELOG for JabRef#12967

* Apply case-insensitive comparison only to DOI identifiers

* Apply IntelliJ code formatting to DuplicateCheck and DuplicateCheckTest

* Add tests for case-insensitive DOI duplicate detection

* Fix case-insensitive DOI comparison in duplicate detection

* fix formatting

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: subhramit <subhramit.bb@live.in>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Faneesh Juneja <willowstration@gmail.com>
Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
Co-authored-by: Paul <thecoder777.github@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>
Co-authored-by: Mend Renovate <bot@renovateapp.com>
Co-authored-by: Nishant Dasgupta <nishant.24bcs10451@sst.scaler.com>
Co-authored-by: Mike Zhang <97817030+mikezhanghaozhe@users.noreply.github.com>
Co-authored-by: JunWang222 <70090336+JunWang222@users.noreply.github.com>
Co-authored-by: AbhijitBhowmick <94289124+AbhijitBhowmick@users.noreply.github.com>
FynnianB pushed a commit to FynnianB/jabref that referenced this pull request Mar 19, 2026
…JabRef#15292)

* Add 'All' citation fetcher that aggregates and deduplicates results from all providers

- Implements CitationFetcher as AllCitationFetcher aggregating CrossRef,
  OpenAlex, OpenCitations, and SemanticScholar
- Deduplicates results using DuplicateCheck with BibDatabaseMode.BIBTEX
- Returns maximum citation count across all providers
- Tolerates individual provider failures gracefully
- Adds ALL entry to CitationFetcherType enum and factory method
- Covers behaviour with unit tests (failure tolerance, deduplication, max count)

Closes JabRef#15029

* Add 'All' citation fetcher that aggregates results from all providers

- Add ALL as first entry in CitationFetcherType enum
- Implement AllCitationFetcher aggregating CrossRef, OpenAlex,
  OpenCitations, and SemanticScholar
- Union results using DatabaseMerger with keyword separator from
  ImportFormatPreferences, as specified in the task
- Return maximum citation count across all providers
- Tolerate individual provider failures gracefully
- Fix race condition in SearchCitationsRelationsService by marking
  citationFetcher and citationCountFetcher fields as volatile
- Set ALL as the default citation fetcher in preferences
- Add unit tests covering failure tolerance, deduplication, and
  max citation count

Closes JabRef#15029

* Update CHANGELOG for issue JabRef#15029

* Address bot review: fix AllCitationFetcher and improve tests

- Build provider list from CitationFetcherType enum (excluding ALL)
  to avoid duplicate list that can drift when new providers are added
- Track anySuccess in fetch() and getCitationCount(); throw
  FetcherException when all providers fail instead of silently
  returning empty results
- Emit WARN log when some providers fail but others succeed
- Rename test variables to intent-revealing names
- Fix citation count assertion to use assertEquals(Optional.of(20))
- Add tests for all-providers-fail and partial-failure scenarios

* Trigger CI

* Reformat AllCitationFetcher

* Fix checkstyle: remove blank line at start of constructor block

* Reverted back to semantic scholar ui preference

* Revert default citation fetcher to SEMANTIC_SCHOLAR in EntryEditorPreferences

* Re-trigger CI

* Adapt tests to use real constructor with mocks, remove test constructor

* fix unchecked excpetion

---------

Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>
FynnianB pushed a commit to FynnianB/jabref that referenced this pull request Mar 19, 2026
* Close entry editor when last library is closed

When no library tab is active, the entry editor remained visible.
Added close() call in the activeTabProperty listener's else branch
to handle the zero-libraries-open case.

Fixes JabRef#13125

* Update CHANGELOG for JabRef#13125

* Fix case-insensitive DOI comparison in duplicate detection (JabRef#12967)

* Chore(deps): Bump org.gradlex:java-module-dependencies in /build-logic (JabRef#15328)

Bumps [org.gradlex:java-module-dependencies](https://github.com/gradlex-org/java-module-dependencies) from 1.12 to 1.12.1.
- [Release notes](https://github.com/gradlex-org/java-module-dependencies/releases)
- [Changelog](https://github.com/gradlex-org/java-module-dependencies/blob/main/CHANGELOG.md)
- [Commits](gradlex-org/java-module-dependencies@v1.12...v1.12.1)

---
updated-dependencies:
- dependency-name: org.gradlex:java-module-dependencies
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.openrewrite.rewrite from 7.26.0 to 7.28.1 (JabRef#15326)

Bumps org.openrewrite.rewrite from 7.26.0 to 7.28.1.

---
updated-dependencies:
- dependency-name: org.openrewrite.rewrite
  dependency-version: 7.28.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.mockito:mockito-core in /versions (JabRef#15330)

Bumps [org.mockito:mockito-core](https://github.com/mockito/mockito) from 5.22.0 to 5.23.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](mockito/mockito@v5.22.0...v5.23.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-core
  dependency-version: 5.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.cyclonedx.bom from 3.2.0 to 3.2.1 (JabRef#15327)

Bumps org.cyclonedx.bom from 3.2.0 to 3.2.1.

---
updated-dependencies:
- dependency-name: org.cyclonedx.bom
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump com.squareup.okio:okio-jvm in /versions (JabRef#15329)

Bumps [com.squareup.okio:okio-jvm](https://github.com/square/okio) from 3.16.4 to 3.17.0.
- [Changelog](https://github.com/square/okio/blob/master/CHANGELOG.md)
- [Commits](square/okio@parent-3.16.4...parent-3.17.0)

---
updated-dependencies:
- dependency-name: com.squareup.okio:okio-jvm
  dependency-version: 3.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* New translations jabref_en.properties (Italian) (JabRef#15334)

* RIS export SP/EP fields when pages contain Unicode en-dash or em-dash (JabRef#15315)

* Extend the split regex to match en-dash and em-dash

* Added tests

---------

Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* Remove object redundancy, miscellaneous refactoring (JabRef#15332)

* Remove object redundancy, miscellaneous refactoring

Signed-off-by: subhramit <subhramit.bb@live.in>

* Use abbreviationRepository parameter

Signed-off-by: subhramit <subhramit.bb@live.in>

* Use less injections for journal abbreviations repository

Signed-off-by: subhramit <subhramit.bb@live.in>

* Indent

Signed-off-by: subhramit <subhramit.bb@live.in>

* Revert to codepoint

---------

Signed-off-by: subhramit <subhramit.bb@live.in>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>

* Add drag-and-drop support for Citation Relations tab (JabRef#15181)

* Add drag-and-drop support for Citation Relations tab

- Implement drag detection in CitationRelationsTab to allow dragging entries
- Add drag support to ViewModelListCellFactory
- Fix NullPointerException in FrameDndHandler when dropping onto tabs without IDs
- Fixes JabRef#15135

* Fix: correctly set drop completion status for entries

* Fix: Add Unreleased section and moved changelog entries

* Fix CHANGELOG formatting and upstream linter errors; removed empty groups

* Fix code consistency for cr

* Add explicit type

* Consistency in CHANGELOG.md

---------

Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>

* Update dependency org.eclipse.jgit:org.eclipse.jgit.pgm to v7.6.0.202603022253-r (JabRef#15335)

* Chore(deps): Bump org.cyclonedx.bom from 3.2.1 to 3.2.2 (JabRef#15337)

Bumps org.cyclonedx.bom from 3.2.1 to 3.2.2.

---
updated-dependencies:
- dependency-name: org.cyclonedx.bom
  dependency-version: 3.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Chore(deps): Bump org.eclipse.jgit:org.eclipse.jgit in /versions (JabRef#15338)

Bumps [org.eclipse.jgit:org.eclipse.jgit](https://github.com/eclipse-jgit/jgit) from 7.5.0.202512021534-r to 7.6.0.202603022253-r.
- [Commits](eclipse-jgit/jgit@v7.5.0.202512021534-r...v7.6.0.202603022253-r)

---
updated-dependencies:
- dependency-name: org.eclipse.jgit:org.eclipse.jgit
  dependency-version: 7.6.0.202603022253-r
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add 'All' citation fetcher that aggregates results from all providers (JabRef#15292)

* Add 'All' citation fetcher that aggregates and deduplicates results from all providers

- Implements CitationFetcher as AllCitationFetcher aggregating CrossRef,
  OpenAlex, OpenCitations, and SemanticScholar
- Deduplicates results using DuplicateCheck with BibDatabaseMode.BIBTEX
- Returns maximum citation count across all providers
- Tolerates individual provider failures gracefully
- Adds ALL entry to CitationFetcherType enum and factory method
- Covers behaviour with unit tests (failure tolerance, deduplication, max count)

Closes JabRef#15029

* Add 'All' citation fetcher that aggregates results from all providers

- Add ALL as first entry in CitationFetcherType enum
- Implement AllCitationFetcher aggregating CrossRef, OpenAlex,
  OpenCitations, and SemanticScholar
- Union results using DatabaseMerger with keyword separator from
  ImportFormatPreferences, as specified in the task
- Return maximum citation count across all providers
- Tolerate individual provider failures gracefully
- Fix race condition in SearchCitationsRelationsService by marking
  citationFetcher and citationCountFetcher fields as volatile
- Set ALL as the default citation fetcher in preferences
- Add unit tests covering failure tolerance, deduplication, and
  max citation count

Closes JabRef#15029

* Update CHANGELOG for issue JabRef#15029

* Address bot review: fix AllCitationFetcher and improve tests

- Build provider list from CitationFetcherType enum (excluding ALL)
  to avoid duplicate list that can drift when new providers are added
- Track anySuccess in fetch() and getCitationCount(); throw
  FetcherException when all providers fail instead of silently
  returning empty results
- Emit WARN log when some providers fail but others succeed
- Rename test variables to intent-revealing names
- Fix citation count assertion to use assertEquals(Optional.of(20))
- Add tests for all-providers-fail and partial-failure scenarios

* Trigger CI

* Reformat AllCitationFetcher

* Fix checkstyle: remove blank line at start of constructor block

* Reverted back to semantic scholar ui preference

* Revert default citation fetcher to SEMANTIC_SCHOLAR in EntryEditorPreferences

* Re-trigger CI

* Adapt tests to use real constructor with mocks, remove test constructor

* fix unchecked excpetion

---------

Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>

* Avoid error logs when search queries are incomplete (JabRef#15333)

* Avoid error logs when search queries are incomplete

Log the parsing error at debug level instead of error level. This prevents having
unnecessary output when user is still entering input like "title =".

* Update changelog for fixing incomplete search logging issue

* Update changelog entry for incomplete search logging issue

* Refine changelog entry for incomplete search logging issue

* Chore(deps): Bump org.openrewrite.recipe:rewrite-recipe-bom from 3.24.0 to 3.25.0 (JabRef#15217)

* Chore(deps): Bump org.openrewrite.recipe:rewrite-recipe-bom

Bumps [org.openrewrite.recipe:rewrite-recipe-bom](https://github.com/openrewrite/rewrite-recipe-bom) from 3.24.0 to 3.25.0.
- [Release notes](https://github.com/openrewrite/rewrite-recipe-bom/releases)
- [Commits](openrewrite/rewrite-recipe-bom@v3.24.0...v3.25.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.recipe:rewrite-recipe-bom
  dependency-version: 3.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* udpate plugin

* update rewrite

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>

* Select better value in MultiMergeEntries dialog component (JabRef#15027) (JabRef#15255)

* Select better value in MultiMergeEntries dialog component (JabRef#15027)

* Use PlausibilityComparatorFactory in MultiMergeEntriesViewModel
to select the more plausible value when merging fields from
multiple sources, instead of always keeping the first-seen value.

* Add DateFieldPlausibilityComparator to prefer more specific dates.

* Add unit tests for DateFieldPlausibilityComparator

* implement review comments

* Fix trailing whitespace in MultiMergeEntriesViewModelTest

* Trigger CI

* CI: re-trigger

* CI: re-trigger

---------

Co-authored-by: Christoph <siedlerkiller@gmail.com>

* Fix reset and import for PreviewPreferences (JabRef#15306)

* Cleanups

* Refactor PreviewPreferences for resetting and import

* Some null checks and migrations

* Fix wrong notnull

* Fix import

* Avoid addAll crash on immutable List

* Add forgotten customPreviewLayout

* Fix artifact from code iteration

* Refactor for consistency

* Fix artifact from code iteration

* Enhance dummy fallback layout

* Try to fix jbang

* Apply IDE suggestions

* Fix weird checkstyle behaviour

* Add default styles

* Fix migration tests

* Add tests

* Small cleanups

---------

Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>

* Fix javadoc markdown artifacts (JabRef#15309)

* Closes JabRef#14897
This incorporates all the pending old Javadoc to  Markdown changes required after merging JabRef#14891.The following files are changed:
1.AutoCompletionTextInputBinding.java
2.JabRefCliPreferences.java
3.SearchBasedParserFetcher.java
4.StartNewStudyAction.java
                                             1.

* 1.

* Rsolved mix up of endregion and endRegion.Final one is endregion.
1.File changed-JabRefCliPreferences.java

* Rsolved format issue related to line space.Files changed.
1.JabRefCliPreferences.java
2.SearchBasedParserFetcher.java

* Files changed.
1.JabRefCliPreferences.java.
The following changes are done:-
1.Added // endregion to maintain sync with region:AI
  And // region Push to application preferences and //region to Git
2.Changed region: to region
3.Changed region: Cleanup to previous ToDo: Cleanup
4.changed endRegion to end region
5.Adjusted  dangling // endregion by merging Imported Preference tag(new one) with Other Preferences(old one)

* Files changed.
1.JabRefCliPreferences.java.
The following changes are done:-
1.Apply IntelliJ formatting

* Update CHANGELOG for JabRef#12967

* Apply case-insensitive comparison only to DOI identifiers

* Apply IntelliJ code formatting to DuplicateCheck and DuplicateCheckTest

* Add tests for case-insensitive DOI duplicate detection

* Fix case-insensitive DOI comparison in duplicate detection

* fix formatting

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: subhramit <subhramit.bb@live.in>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Faneesh Juneja <willowstration@gmail.com>
Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
Co-authored-by: Paul <thecoder777.github@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>
Co-authored-by: Mend Renovate <bot@renovateapp.com>
Co-authored-by: Nishant Dasgupta <nishant.24bcs10451@sst.scaler.com>
Co-authored-by: Mike Zhang <97817030+mikezhanghaozhe@users.noreply.github.com>
Co-authored-by: JunWang222 <70090336+JunWang222@users.noreply.github.com>
Co-authored-by: AbhijitBhowmick <94289124+AbhijitBhowmick@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

good second issue Issues that involve a tour of two or three interweaved components in JabRef status: no-bot-comments 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.

Enable merging of citation informations

5 participants