Add 'All' citation fetcher that aggregates results from all providers#15292
Conversation
…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
Review Summary by QodoAdd "All" citation fetcher aggregating results from all providers
WalkthroughsDescription• 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 Diagramflowchart 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"]
File Changes1. jablib/src/main/java/org/jabref/logic/importer/fetcher/citation/AllCitationFetcher.java
|
Code Review by Qodo
1.
|
There was a problem hiding this comment.
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
AllCitationFetcherand wire it intoCitationFetcherType(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.
| 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); | ||
| } |
There was a problem hiding this comment.
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.
| 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); | ||
| } | ||
| } |
There was a problem hiding this comment.
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.
- 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
There was a problem hiding this comment.
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.
| for (CitationFetcherType type : CitationFetcherType.values()) { | ||
| if (type == CitationFetcherType.ALL) { | ||
| continue; | ||
| } | ||
| providers.add(type.buildCitationFetcher( | ||
| importerPreferences, | ||
| importFormatPreferences, | ||
| citationKeyPatternPreferences, | ||
| grobidPreferences, | ||
| aiService)); | ||
| } |
There was a problem hiding this comment.
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.
| 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()); | ||
| } |
There was a problem hiding this comment.
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.
| 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; |
There was a problem hiding this comment.
There are several unused imports (e.g., OpenAlex, CrossRefCitationFetcher, OpenCitationsFetcher, SemanticScholarCitationFetcher). These are likely to fail formatting/static-analysis checks; please remove unused imports.
| 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; |
| 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); | ||
| } | ||
| } |
There was a problem hiding this comment.
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).
8c4add3 to
a04bad2
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| private volatile CitationFetcher citationFetcher; | ||
| private volatile CitationCountFetcher citationCountFetcher; |
There was a problem hiding this comment.
Why do these need to be volatile?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Did you test this? We are not in a highly parallel system.
There was a problem hiding this comment.
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()); |
There was a problem hiding this comment.
"ALL" will cause high load. We should leave this setting untouched.
There was a problem hiding this comment.
ok i have reverted default citation fetcher to SEMANTIC_SCHOLAR
…jabref into issue-15029-clean
This comment has been minimized.
This comment has been minimized.
| } | ||
|
|
||
| // Test constructor | ||
| AllCitationFetcher(List<CitationFetcher> fetchers) { |
There was a problem hiding this comment.
Adapt the test to use the real constructur, just use mocks. This ensures that you are testing the constructor logic as well
There was a problem hiding this comment.
Done. Removed the test constructor and rewrote the tests to use the real constructor, following the same pattern as CrossRefCitationFetcherTest, OpenAlexCitationFetcherTest .
|
overall okay, just adapt the test to use the normal constructor |
This comment has been minimized.
This comment has been minimized.
| max = max.isEmpty() ? count : Optional.of(Math.max(max.get(), count.get())); | ||
| } | ||
| } catch (FetcherException e) { | ||
| } catch (Exception e) { |
There was a problem hiding this comment.
Only catch FetcherException! Did your AI tool change this?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
i will revert back to FetcherException then
There was a problem hiding this comment.
Do you have the full stacktrace?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
Thanks for the hint! I refactored this so that only a FetcherException is now thrown
| } | ||
|
|
||
| @Test | ||
| void removesDuplicateEntries() throws Exception { |
There was a problem hiding this comment.
You can tes them independently
There was a problem hiding this comment.
Should I restore the test constructor to inject mock fetchers for these tests and keeping the real constructor tests separate?
|
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. |
This comment has been minimized.
This comment has been minimized.
✅ All tests passed ✅🏷️ Commit: 3c9a984 Learn more about TestLens at testlens.app. |
…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>
* 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>
…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>
* 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>
…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>
* 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>
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
Checklist
CHANGELOG.mdin a way that can be understood by the average user (if change is visible to the user)