Skip to content

fix(fetchers): fix OpenAlex entry type assignment - #16533

Open
InAnYan wants to merge 5 commits into
JabRef:mainfrom
InAnYan:refactor/open-alex-1
Open

fix(fetchers): fix OpenAlex entry type assignment#16533
InAnYan wants to merge 5 commits into
JabRef:mainfrom
InAnYan:refactor/open-alex-1

Conversation

@InAnYan

@InAnYan InAnYan commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

Just adds a mapping from OpenAlex work type to bibentry type

Steps to test

Nothing really much. Just fetch a conference paper, and it should be InProceedings. For example this:

ImageNet: A large-scale hierarchical image database

ID: W2108598243

Related issues and pull requests

Closes NA

AI usage

I have used Gemini to map the types, and GPT to write the code. The code proposed by AI was edited and analyzed.

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • If AI tools were used, I disclosed them in the "AI usage" section and reviewed, understood, and take full ownership of all AI-generated code
  • 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

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

qodo-free-for-open-source-projects Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Fix OpenAlex work-type → BibEntry type mapping

🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Map OpenAlex work.type values to correct JabRef/BibLaTeX entry types.
• Fall back to UnknownEntryType for unmapped OpenAlex types.
• Tighten null/empty handling and align OpenAlex fetcher tests with new typing.
Diagram

graph TD
  api{{"OpenAlex Works API"}} --> fetcher["OpenAlex fetcher"] --> json["Work JSON"] --> mapper["Type mapper"] --> etype["EntryType"] --> bib[("BibEntry")]
  
  subgraph Legend
    direction LR
    _ext{{"External"}} ~~~ _svc["Component"] ~~~ _data[("Data")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Map using OpenAlex `type_crossref` (when present)
  • ➕ Could align better with established Crossref type semantics
  • ➕ May reduce maintenance if OpenAlex expands type taxonomy
  • ➖ Requires requesting/handling an additional field and fallback logic
  • ➖ Still needs a mapping layer into JabRef EntryType values
2. Move type mapping into a shared mapping utility + parameterized tests
  • ➕ Centralizes mappings for reuse by other fetchers
  • ➕ Encourages exhaustive coverage of all OpenAlex types
  • ➖ More structural change than necessary for a targeted bug fix
  • ➖ Slightly higher upfront refactor cost

Recommendation: The in-fetcher static mapping is an appropriate, low-risk fix for incorrect entry typing and keeps behavior explicit. If mapping logic grows or becomes shared, extracting it into a dedicated utility with parameterized tests would be the next step.

Files changed (2) +56 / -8

Bug fix (1) +53 / -6
OpenAlex.javaAdd OpenAlex work-type → EntryType mapping and safer parsing +53/-6

Add OpenAlex work-type → EntryType mapping and safer parsing

• Introduces a normalized mapping from OpenAlex 'type' values to JabRef/BibLaTeX 'EntryType's, including a fallback to 'UnknownEntryType'. Updates JSON parsing to use this mapping, improves null/empty handling in a few places, and applies small functional-style refactors.

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java

Tests (1) +3 / -2
OpenAlexFetcherTest.javaUpdate expected entry type for OpenAlex search result +3/-2

Update expected entry type for OpenAlex search result

• Adjusts the master expected 'BibEntry' to 'InProceedings' (conference paper) and clears date/year fields to avoid assertion instability from OpenAlex-provided publication date/year differences.

jablib/src/test/java/org/jabref/logic/importer/fetcher/OpenAlexFetcherTest.java

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

qodo-free-for-open-source-projects Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. openAlexType nullable unannotated 📘 Rule violation ≡ Correctness
Description
In the @NullMarked OpenAlex class, code uses optString(..., null) to pull JSON values like
type/id, allowing null to be produced and assigned to an unannotated String (e.g.,
openAlexType) or flow through the API-URI mapping. This violates the JSpecify non-null-by-default
contract and can undermine nullness analysis or lead to null-related defects.
Code

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[R225-228]

+            String openAlexType = item.optString("type", null);
+            if (openAlexType != null) {
+                entry.setType(mapOpenAlexTypeToEntryType(openAlexType));
+            }
Evidence
Compliance ID 8 requires JSpecify-consistent nullability under @NullMarked, including avoiding
explicitly passing or propagating null unless it is explicitly expected/annotated. The cited code
is inside an @NullMarked OpenAlex class and explicitly passes null as the default to
optString (e.g., item.optString("type", null) and work.optString("id", null)), which means
optString may return null when keys are absent; that nullable result is then stored in an
unannotated String (openAlexType) or used in the getCitationsApiUri mapping, directly
conflicting with the non-null-by-default contract.

AGENTS.md: Nullability Must Use JSpecify; New Classes Must Be @NullMarked; Avoid Passing/Returning null in New Public APIs: AGENTS.md: Nullability Must Use JSpecify; New Classes Must Be @NullMarked; Avoid Passing/Returning null in New Public APIs: AGENTS.md: Nullability Must Use JSpecify; New Classes Must Be @NullMarked; Avoid Passing/Returning null in New Public APIs: AGENTS.md: Nullability Must Use JSpecify; New Classes Must Be @NullMarked; Avoid Passing/Returning null in New Public APIs
jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[53-57]
jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[220-228]
jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[468-473]

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

## Issue description
`OpenAlex` is `@NullMarked` (non-null by default), but it currently calls `optString(..., null)` (e.g., for `type` and `id`), which can produce `null` and then assigns/propagates that value via unannotated `String` variables (like `openAlexType`) or through the `getCitationsApiUri` mapping. Replace this pattern with a non-null/blank-based approach or make nullability explicit with `@Nullable` where `null` is truly expected.
## Issue Context
Under `@NullMarked`, all type usages are non-null unless explicitly annotated otherwise; passing `null` as the default to `optString` means missing JSON keys can yield `null`, violating the JSpecify contract and potentially breaking nullness analysis. Compliance ID 8 specifically calls for JSpecify-consistent null handling and avoiding explicit `null` passing/propagation unless explicitly expected.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[220-229]
- jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[468-477]

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



Remediation recommended

2. BibLaTeX-only types mapped 🐞 Bug ≡ Correctness
Description
OpenAlex maps some OpenAlex work types to BibLaTeX-exclusive EntryTypes (e.g.,
BiblatexNonStandardEntryType.Review, StandardEntryType.Report/Thesis/Online/Dataset/Software).
In BibTeX-mode libraries this triggers an integrity warning (BibTeXEntryTypeChecker) and exports
the non-BibTeX entry type header verbatim, which many BibTeX toolchains may not recognize.
Code

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[R75-78]

+            Map.entry("reference-entry", StandardEntryType.InReference),
+            Map.entry("book-review", BiblatexNonStandardEntryType.Review),
+            Map.entry("libguides", StandardEntryType.Online),
+            Map.entry("peer-review", BiblatexNonStandardEntryType.Review),
Evidence
The mapping table now returns BibLaTeX-only types (as categorized in StandardEntryType and
BiblatexNonStandardEntryType). JabRef explicitly flags such types in BibTeX mode via
BibTeXEntryTypeChecker using EntryTypeFactory.isExclusiveBiblatex, and export writes the entry
type header from the EntryType display name without mode-based normalization, so these
BibLaTeX-only types will be serialized into BibTeX-mode outputs.

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[62-89]
jablib/src/main/java/org/jabref/model/entry/types/StandardEntryType.java[9-43]
jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardEntryType.java[7-21]
jablib/src/main/java/org/jabref/model/entry/types/EntryTypeFactory.java[33-43]
jablib/src/main/java/org/jabref/logic/integrity/BibTeXEntryTypeChecker.java[10-22]
jablib/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java[143-149]

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

## Issue description
OpenAlex’s type mapping includes BibLaTeX-only entry types (notably `BiblatexNonStandardEntryType.Review` and several BibLaTeX-only `StandardEntryType`s). When a user is working in a BibTeX-mode library, JabRef will flag these as “only defined for BibLaTeX” and exported `.bib` files will contain those entry-type headers.
## Issue Context
- `BibTeXEntryTypeChecker` warns in BibTeX mode when `EntryTypeFactory.isExclusiveBiblatex(entry.getType())` is true.
- `StandardEntryType` clearly separates BibTeX vs BibLaTeX-only types in the enum.
- `BibEntryWriter` writes `@` + `entry.getType().getDisplayName()` regardless of database mode.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[62-89]
### Suggested remediation
Adjust the `OPENALEX_TYPE_TO_ENTRY_TYPE` mapping to avoid emitting BibLaTeX-exclusive types when there is a reasonable BibTeX-compatible alternative:
- Map `report` to `StandardEntryType.TechReport` (supported in both definitions).
- Map `dissertation` to `StandardEntryType.PhdThesis` or `StandardEntryType.MastersThesis` (BibTeX types), or fall back to `Misc`.
- Map `book-review` / `peer-review` to a BibTeX-safe type (e.g., `Misc` or `Article`) instead of `BiblatexNonStandardEntryType.Review`.
- Consider a design where the mapping is chosen based on the target library mode (BibTeX vs BibLaTeX) if that information is available at the call site; otherwise prefer BibTeX-safe defaults to avoid generating BibLaTeX-only types unexpectedly.

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


3. Type mapping untested 🐞 Bug ⚙ Maintainability
Description
The newly introduced OpenAlex typeEntryType mapping table is not directly covered by tests
beyond the simple "article" case, so regressions or incorrect mappings (e.g.,
conference-paperInProceedings) can ship unnoticed. This makes future edits to the mapping table
risky and hard to validate.
Code

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[R63-66]

+    private static final Map<String, EntryType> OPENALEX_TYPE_TO_ENTRY_TYPE = Map.ofEntries(
+            Map.entry("article", StandardEntryType.Article),
+            Map.entry("other", StandardEntryType.Misc),
+            Map.entry("dataset", StandardEntryType.Dataset),
Evidence
The mapping table and the @VisibleForTesting mapper are new, but the tests shown only assert
parsing when the JSON contains "type":"article" (no coverage for the other mapping keys).

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[62-112]
jablib/src/test/java/org/jabref/logic/importer/fetcher/OpenAlexFetcherTest.java[67-99]

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

## Issue description
A new OpenAlex work-type mapping table (`OPENALEX_TYPE_TO_ENTRY_TYPE`) was added, but tests don’t exercise most mapped values, making mapping regressions likely to go undetected.
### Issue Context
`OpenAlexFetcherTest` currently validates parsing for an `"article"` work type only; it does not assert behavior for key cases like `conference-paper` or unknown values.
### Fix Focus Areas
- jablib/src/test/java/org/jabref/logic/importer/fetcher/OpenAlexFetcherTest.java[57-99]
- jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[62-112]
### Suggested change
- Add a `@ParameterizedTest` that calls `fetcher.mapOpenAlexTypeToEntryType(openAlexType)` and asserts the resulting `EntryType` (e.g., by comparing `getName()` or the enum instance) for representative mappings:
- `conference-paper` → `StandardEntryType.InProceedings`
- `book-chapter` → `StandardEntryType.InBook`
- `preprint` → `StandardEntryType.Online`
- `book-review` → `BiblatexNonStandardEntryType.Review`
- unknown type (e.g., `"made-up"`) → instance of `UnknownEntryType`
- Include a case-insensitivity check (e.g., `"Conference-Paper"`).

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


4. Blank type yields invalid output 🐞 Bug ☼ Reliability
Description
jsonItemToBibEntry sets the entry type for any non-null type string without checking for
blank/whitespace, so a blank OpenAlex type becomes UnknownEntryType(""). UnknownEntryType with
an empty name results in an empty display name, which is serialized by BibEntryWriter as "@{",
producing malformed BibTeX/BibLaTeX.
Code

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[R225-228]

+            String openAlexType = item.optString("type", null);
+            if (openAlexType != null) {
+                entry.setType(mapOpenAlexTypeToEntryType(openAlexType));
+            }
Evidence
The new code path only checks for null and will pass blank strings into the mapper.
UnknownEntryType allows empty names, and BibEntryWriter uses getDisplayName() to write the
entry header, which would become @{ when display name is empty.

jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[220-229]
jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[102-112]
jablib/src/main/java/org/jabref/model/entry/types/UnknownEntryType.java[13-35]
jablib/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java[143-149]

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 OpenAlex `type` field is only null-checked before mapping; blank values can flow into `UnknownEntryType("")`, which later serializes to malformed output (`@{`).
### Issue Context
- `jsonItemToBibEntry` calls `mapOpenAlexTypeToEntryType(openAlexType)` when `openAlexType != null`.
- `UnknownEntryType` stores the provided name (lowercased) without validating non-emptiness.
- `BibEntryWriter` writes `'@' + entry.getType().getDisplayName()`; an empty display name yields `@{`.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[220-229]
- jablib/src/main/java/org/jabref/model/entry/types/UnknownEntryType.java[13-35]
- jablib/src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java[143-149]
### Suggested change
- In `jsonItemToBibEntry`, change the condition to guard blank values:
- `if (StringUtil.isNotBlank(openAlexType)) { entry.setType(mapOpenAlexTypeToEntryType(openAlexType)); }`
- Otherwise, leave the default type (`BibEntry.DEFAULT_TYPE` / `Misc`) or explicitly set it.
- Optionally harden `mapOpenAlexTypeToEntryType` by trimming input before lowercasing/lookup.
- Add a unit test ensuring blank `type` does not produce an empty/invalid entry type (e.g., remains `misc`).

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


Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@github-actions github-actions Bot added the status: changes-required Pull requests that are not yet complete label Aug 11, 2026
@InAnYan
InAnYan marked this pull request as draft August 12, 2026 07:32
@InAnYan
InAnYan marked this pull request as ready for review August 12, 2026 16:59
Comment on lines +75 to +78
Map.entry("reference-entry", StandardEntryType.InReference),
Map.entry("book-review", BiblatexNonStandardEntryType.Review),
Map.entry("libguides", StandardEntryType.Online),
Map.entry("peer-review", BiblatexNonStandardEntryType.Review),

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.

Remediation recommended

1. Biblatex-only types mapped 🐞 Bug ≡ Correctness

OpenAlex maps some OpenAlex work types to BibLaTeX-exclusive EntryTypes (e.g.,
BiblatexNonStandardEntryType.Review, StandardEntryType.Report/Thesis/Online/Dataset/Software).
In BibTeX-mode libraries this triggers an integrity warning (BibTeXEntryTypeChecker) and exports
the non-BibTeX entry type header verbatim, which many BibTeX toolchains may not recognize.
Agent Prompt
## Issue description
OpenAlex’s type mapping includes BibLaTeX-only entry types (notably `BiblatexNonStandardEntryType.Review` and several BibLaTeX-only `StandardEntryType`s). When a user is working in a BibTeX-mode library, JabRef will flag these as “only defined for BibLaTeX” and exported `.bib` files will contain those entry-type headers.

## Issue Context
- `BibTeXEntryTypeChecker` warns in BibTeX mode when `EntryTypeFactory.isExclusiveBiblatex(entry.getType())` is true.
- `StandardEntryType` clearly separates BibTeX vs BibLaTeX-only types in the enum.
- `BibEntryWriter` writes `@` + `entry.getType().getDisplayName()` regardless of database mode.

## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/importer/fetcher/OpenAlex.java[62-89]

### Suggested remediation
Adjust the `OPENALEX_TYPE_TO_ENTRY_TYPE` mapping to avoid emitting BibLaTeX-exclusive types when there is a reasonable BibTeX-compatible alternative:
- Map `report` to `StandardEntryType.TechReport` (supported in both definitions).
- Map `dissertation` to `StandardEntryType.PhdThesis` or `StandardEntryType.MastersThesis` (BibTeX types), or fall back to `Misc`.
- Map `book-review` / `peer-review` to a BibTeX-safe type (e.g., `Misc` or `Article`) instead of `BiblatexNonStandardEntryType.Review`.
- Consider a design where the mapping is chosen based on the target library mode (BibTeX vs BibLaTeX) if that information is available at the call site; otherwise prefer BibTeX-safe defaults to avoid generating BibLaTeX-only types unexpectedly.

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

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

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit ce757d9

@InAnYan

InAnYan commented Aug 13, 2026

Copy link
Copy Markdown
Member Author

jabgui tests:

Details > Task :jabgui:test

LinkedFileViewModelTest > downloadHtmlFileCausesWarningDisplay(Boolean, String) > [1] "true", "Download 'https://www.google.com/

' was a HTML file. Keeping URL." FAILED
org.mockito.exceptions.verification.WantedButNotInvoked at LinkedFileViewModelTest.java:207

LinkedFileViewModelTest > downloadHtmlFileCausesWarningDisplay(Boolean, String) > [2] "false", "Download 'https://www.google.com/

' was a HTML file. Removed." FAILED
org.mockito.exceptions.verification.WantedButNotInvoked at LinkedFileViewModelTest.java:207

I think unrelated to my PR?

Fetchers test - almost all unrelated, but this:

OpenAlexFetcherTest > searchByQuotedQueryFindsEntry() FAILED
    org.opentest4j.AssertionFailedError at OpenAlexFetcherTest.java:192

Was failing before

@InAnYan

InAnYan commented Aug 13, 2026

Copy link
Copy Markdown
Member Author

Fixed OpenAlex tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: changes-required Pull requests that are not yet complete

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants