Verified Owner
Top Description Inners Fields Constructors Methods
org.jabref.http.server.services

public Class CitationCacheService

extends Object
Class Inheritance
Annotations
@Singleton
Imports
java.time.Duration, .Instant, java.util.Optional, org.jabref.model.entry.BibEntry, com.github.benmanes.caffeine.cache.Cache, .Caffeine, io.github.thibaultmeyer.cuid.CUID, jakarta.inject.Singleton

Caches the result of a plain-citation → BibEntry conversion so a hover existence check and a subsequent add-to-library don't both pay the LLM / fetcher cost.

Two complementary maps:

  1. Token cache — keyed by a server-issued CUID2 returned from the lookup endpoint. The matching add endpoint consumes the key. Short TTL so a stale token can't resurrect an unrelated citation across sessions.
  2. Text cache — keyed by the raw citation text itself. Lets a repeat /lookup (or batched /lookup:batch) skip the LLM / fetcher parse entirely when the same citation string has been parsed recently (e.g. SumatraPDF re-scans a visible PDF page after the user jumps back to it). Longer TTL than the token cache because the parsed BibEntry stays valid as long as the citation text does.

Nested and Inner Type Summary

Modifier and TypeClass and Description
public static record

Field Summary

Modifier and TypeField and Description
private static final int
CUID_LENGTH

Token length picked to match the CUID2 size already used by BibFieldsIndexer: long enough to be collision-resistant in a 256-slot cache without being noisy in HTTP responses.

private static final int
private static final Duration
private final Cache<String, CitationCacheService.CachedCitation>
private static final int
private static final Duration
private final Cache<String, CitationCacheService.CachedCitation>

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
public Optional<CitationCacheService.CachedCitation>
get(String key)

Returns the cached citation, or empty when the token has expired or was never issued.

public Optional<CitationCacheService.CachedCitation>
getByText(String citationText)

Returns the cached parse for the given citation text, or empty on miss.

public void
invalidate(String key)

Drops the cache entry; called by the add endpoint after a successful import so a stale token can't be re-used to add a duplicate.

public String
put(BibEntry parsed, String rawCitation)

Stores a parsed citation and returns the token the client should send back to the add endpoint.

public void
putByText(BibEntry parsed, String rawCitation)

Stashes a parsed citation under its raw text so a later /lookup for the same text can skip the LLM parse.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

CUID_LENGTHback to summary
private static final int CUID_LENGTH

Token length picked to match the CUID2 size already used by BibFieldsIndexer: long enough to be collision-resistant in a 256-slot cache without being noisy in HTTP responses.

TEXT_MAX_ENTRIESback to summary
private static final int TEXT_MAX_ENTRIES
TEXT_TTLback to summary
private static final Duration TEXT_TTL
textCacheback to summary
private final Cache<String, CitationCacheService.CachedCitation> textCache
TOKEN_MAX_ENTRIESback to summary
private static final int TOKEN_MAX_ENTRIES
TOKEN_TTLback to summary
private static final Duration TOKEN_TTL
tokenCacheback to summary
private final Cache<String, CitationCacheService.CachedCitation> tokenCache

Constructor Detail

CitationCacheServiceback to summary
public CitationCacheService()

Method Detail

getback to summary
public Optional<CitationCacheService.CachedCitation> get(String key)

Returns the cached citation, or empty when the token has expired or was never issued. Does not evict on read so the same lookup result can be added more than once (idempotent across retries).

getByTextback to summary
public Optional<CitationCacheService.CachedCitation> getByText(String citationText)

Returns the cached parse for the given citation text, or empty on miss.

invalidateback to summary
public void invalidate(String key)

Drops the cache entry; called by the add endpoint after a successful import so a stale token can't be re-used to add a duplicate.

putback to summary
public String put(BibEntry parsed, String rawCitation)

Stores a parsed citation and returns the token the client should send back to the add endpoint.

putByTextback to summary
public void putByText(BibEntry parsed, String rawCitation)

Stashes a parsed citation under its raw text so a later /lookup for the same text can skip the LLM parse. The token-keyed cache is left untouched — callers mint a fresh token via put for each lookup.

org.jabref.http.server.services back to summary

public final Record CitationCacheService.CachedCitation

extends Record
Class Inheritance
Record Components
parsed:BibEntry 
rawCitation:String 
createdAt:Instant 

Field Summary

Modifier and TypeField and Description
private final Instant
createdAt

Record Component accessed by createdAt().

private final BibEntry
parsed

Record Component accessed by parsed().

private final String
rawCitation

Record Component accessed by rawCitation().

Constructor Summary

AccessConstructor and Description
public
CachedCitation(BibEntry parsed, String rawCitation, Instant createdAt)

Method Summary

Modifier and TypeMethod and Description
public Instant
createdAt()

Record Component getter of createdAt.

public final boolean
equals(Object o)

Implements abstract java.lang.Record.equals.

Indicates whether some other object is "equal to" this one.

public final int
hashCode()

Implements abstract java.lang.Record.hashCode.

Returns a hash code value for the record.

public BibEntry
parsed()

Record Component getter of parsed.

public String
rawCitation()

Record Component getter of rawCitation.

public final String
toString()

Implements abstract java.lang.Record.toString.

Returns a string representation of the record.

Field Detail

createdAtback to summary
private final Instant createdAt

Record Component accessed by createdAt().

parsedback to summary
private final BibEntry parsed

Record Component accessed by parsed().

rawCitationback to summary
private final String rawCitation

Record Component accessed by rawCitation().

Constructor Detail

CachedCitationback to summary
public CachedCitation(BibEntry parsed, String rawCitation, Instant createdAt)

Method Detail

createdAtback to summary
public Instant createdAt()

Record Component getter of createdAt.

equalsback to summary
public final boolean equals(Object o)

Implements abstract java.lang.Record.equals.

Doc from java.lang.Record.equals.

Indicates whether some other object is "equal to" this one. In addition to the general contract of Object.equals, record classes must further obey the invariant that when a record instance is "copied" by passing the result of the record component accessor methods to the canonical constructor, as follows:

    R copy = new R(r.c1(), r.c2(), ..., r.cn());
then it must be the case that r.equals(copy).
hashCodeback to summary
public final int hashCode()

Implements abstract java.lang.Record.hashCode.

Doc from java.lang.Record.hashCode.

Returns a hash code value for the record. Obeys the general contract of Object.hashCode. For records, hashing behavior is constrained by the refined contract of Record.equals, so that any two records created from the same components must have the same hash code.

parsedback to summary
public BibEntry parsed()

Record Component getter of parsed.

rawCitationback to summary
public String rawCitation()

Record Component getter of rawCitation.

toStringback to summary
public final String toString()

Implements abstract java.lang.Record.toString.

Doc from java.lang.Record.toString.

Returns a string representation of the record. In accordance with the general contract of Object#toString(), the toString method returns a string that "textually represents" this record. The result should be a concise but informative representation that is easy for a person to read.

In addition to this general contract, record classes must further participate in the invariant that any two records which are equal must produce equal strings. This invariant is necessarily relaxed in the rare case where corresponding equal component values might fail to produce equal strings for themselves.