diff --git a/jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java b/jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java
index b7d3c3378dd..9356407be71 100644
--- a/jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java
+++ b/jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java
@@ -116,6 +116,9 @@ public AiPreferences(boolean enableAi,
this.ragMaxResultsCount = new SimpleIntegerProperty(ragMaxResultsCount);
this.ragMinScore = new SimpleDoubleProperty(ragMinScore);
+ this.apiKeyChangeListener = () -> {
+ };
+
this.templates = Map.of(
AiTemplate.CHATTING_SYSTEM_MESSAGE, new SimpleStringProperty(templates.get(AiTemplate.CHATTING_SYSTEM_MESSAGE)),
AiTemplate.CHATTING_USER_MESSAGE, new SimpleStringProperty(templates.get(AiTemplate.CHATTING_USER_MESSAGE)),
@@ -550,14 +553,14 @@ public void apiKeyUpdated() {
}
public void setTemplate(AiTemplate aiTemplate, String template) {
- templates.get(aiTemplate).set(template);
+ templateProperty(aiTemplate).set(template);
}
public String getTemplate(AiTemplate aiTemplate) {
- return templates.get(aiTemplate).get();
+ return templateProperty(aiTemplate).get();
}
public StringProperty templateProperty(AiTemplate aiTemplate) {
- return templates.get(aiTemplate);
+ return templates.getOrDefault(aiTemplate, new SimpleStringProperty(""));
}
}
diff --git a/jablib/src/main/java/org/jabref/logic/ai/ingestion/MVStoreEmbeddingStore.java b/jablib/src/main/java/org/jabref/logic/ai/ingestion/MVStoreEmbeddingStore.java
index 70446cee9ab..dcfedca606d 100644
--- a/jablib/src/main/java/org/jabref/logic/ai/ingestion/MVStoreEmbeddingStore.java
+++ b/jablib/src/main/java/org/jabref/logic/ai/ingestion/MVStoreEmbeddingStore.java
@@ -44,6 +44,9 @@
*
*/
public class MVStoreEmbeddingStore extends MVStoreBase implements EmbeddingStore {
+
+ private static final EmbeddingRecord EMPTY_EMBEDDING_RECORD = new EmbeddingRecord(null, "", new float[0]);
+
// `file` field is nullable, because {@link Optional} can't be serialized.
private record EmbeddingRecord(@Nullable String file, String content, float[] embeddingVector) implements Serializable {
}
@@ -125,7 +128,7 @@ public EmbeddingSearchResult search(EmbeddingSearchRequest request)
PriorityQueue> matches = new PriorityQueue<>(comparator);
applyFilter(request.filter()).forEach(id -> {
- EmbeddingRecord eRecord = embeddingsMap.get(id);
+ EmbeddingRecord eRecord = embeddingsMap.getOrDefault(id, EMPTY_EMBEDDING_RECORD);
double cosineSimilarity = CosineSimilarity.between(Embedding.from(eRecord.embeddingVector), request.queryEmbedding());
double score = RelevanceScore.fromCosineSimilarity(cosineSimilarity);
diff --git a/jablib/src/main/java/org/jabref/logic/ai/ingestion/model/JabRefEmbeddingModel.java b/jablib/src/main/java/org/jabref/logic/ai/ingestion/model/JabRefEmbeddingModel.java
index b203ed92df9..487743d2701 100644
--- a/jablib/src/main/java/org/jabref/logic/ai/ingestion/model/JabRefEmbeddingModel.java
+++ b/jablib/src/main/java/org/jabref/logic/ai/ingestion/model/JabRefEmbeddingModel.java
@@ -74,7 +74,7 @@ public void startRebuildingTask() {
predictorProperty.set(Optional.empty());
new UpdateEmbeddingModelTask(aiPreferences, predictorProperty)
- .onSuccess(v -> {
+ .onSuccess(_ -> {
LOGGER.info("Embedding model was successfully updated");
errorWhileBuildingModel = "";
eventBus.post(new EmbeddingModelBuiltEvent());
@@ -82,7 +82,7 @@ public void startRebuildingTask() {
.onFailure(e -> {
LOGGER.error("An error occurred while building the embedding model", e);
notificationService.notify(Localization.lang("An error occurred while building the embedding model"));
- errorWhileBuildingModel = e.getMessage();
+ errorWhileBuildingModel = e.getMessage() == null ? "" : e.getMessage();
eventBus.post(new EmbeddingModelBuildingErrorEvent());
})
.executeWith(taskExecutor);
diff --git a/jablib/src/main/java/org/jabref/logic/ai/util/MVStoreBase.java b/jablib/src/main/java/org/jabref/logic/ai/util/MVStoreBase.java
index 4a46ab87c20..86a3d21c20a 100644
--- a/jablib/src/main/java/org/jabref/logic/ai/util/MVStoreBase.java
+++ b/jablib/src/main/java/org/jabref/logic/ai/util/MVStoreBase.java
@@ -8,7 +8,7 @@
import org.h2.mvstore.MVStore;
import org.h2.mvstore.MVStoreException;
-import org.jspecify.annotations.Nullable;
+import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,7 +17,7 @@ public abstract class MVStoreBase implements AutoCloseable {
protected MVStore mvStore;
- public MVStoreBase(@Nullable Path path, NotificationService dialogService) {
+ public MVStoreBase(@NonNull Path path, NotificationService dialogService) {
Path mvStorePath = path;
try {
diff --git a/jablib/src/main/java/org/jabref/logic/importer/FetcherException.java b/jablib/src/main/java/org/jabref/logic/importer/FetcherException.java
index c2b9e97d41b..f3447c73caa 100644
--- a/jablib/src/main/java/org/jabref/logic/importer/FetcherException.java
+++ b/jablib/src/main/java/org/jabref/logic/importer/FetcherException.java
@@ -9,6 +9,7 @@
import org.jabref.logic.util.strings.StringUtil;
import org.jabref.model.http.SimpleHttpResponse;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,10 +19,13 @@ public class FetcherException extends JabRefException {
private static final Pattern API_KEY_PATTERN = Pattern.compile("(?i)(?<" + API_KEY_PARAM_NAME + ">api|key|api[-_]?key)=[^&]*");
private static final String REDACTED_STRING = "[REDACTED]";
+ @Nullable
private final String url;
+
+ @Nullable
private final SimpleHttpResponse httpResponse;
- public FetcherException(String url, SimpleHttpResponse httpResponse) {
+ public FetcherException(@Nullable String url, @Nullable SimpleHttpResponse httpResponse) {
// Empty string handled at org.jabref.logic.importer.FetcherException.getPrefix.
super("");
this.url = url;
@@ -87,7 +91,7 @@ public String getLocalizedMessage() {
}
String getRedactedUrl() {
- return getRedactedUrl(url);
+ return getRedactedUrl(url == null ? "" : url);
}
public static String getRedactedUrl(String source) {
diff --git a/jablib/src/main/java/org/jabref/logic/importer/fetcher/ISIDOREFetcher.java b/jablib/src/main/java/org/jabref/logic/importer/fetcher/ISIDOREFetcher.java
index 9712b7c14ad..8286a3ebb37 100644
--- a/jablib/src/main/java/org/jabref/logic/importer/fetcher/ISIDOREFetcher.java
+++ b/jablib/src/main/java/org/jabref/logic/importer/fetcher/ISIDOREFetcher.java
@@ -82,7 +82,7 @@ public Parser getParser() {
} catch (ParserConfigurationException | IOException | SAXException e) {
Unchecked.throwChecked(new FetcherException("Issue with parsing link", e));
}
- return null;
+ return List.of();
};
}
diff --git a/jablib/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java b/jablib/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
index e1e6b5da870..d41b8a8317f 100644
--- a/jablib/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
+++ b/jablib/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java
@@ -221,7 +221,7 @@ public List performSearch(BaseQueryNode queryNode) throws FetcherExcep
html = getPage(url);
// ResearchGate's server blocks when too many request are made
if (!html.getElementsByClass("nova-legacy-v-publication-item__title").hasText()) {
- throw new FetcherException(url, "Required HTML element not found", null);
+ throw new FetcherException(url, "Required HTML element not found", new IllegalStateException("Missing element"));
}
} catch (IOException e) {
throw new FetcherException(url, e);
@@ -230,11 +230,13 @@ public List performSearch(BaseQueryNode queryNode) throws FetcherExcep
Elements sol = html.getElementsByClass("nova-legacy-v-publication-item__title");
List urls = sol.select("a").eachAttr("href").stream()
.filter(stream -> stream.contains("publication/"))
- .map(resultStream -> resultStream.substring(resultStream.indexOf("publication/") + 12, resultStream.indexOf("_")))
+ .map(resultStream -> resultStream.substring(
+ resultStream.indexOf("publication/") + 12,
+ resultStream.indexOf("_")))
.map(idStream -> SEARCH_FOR_BIB_ENTRY + idStream)
.map(this::getInputStream)
- .filter(Objects::nonNull)
- .map(stream -> stream.lines().collect(Collectors.joining(OS.NEWLINE)))
+ .flatMap(Optional::stream)
+ .map(reader -> reader.lines().collect(Collectors.joining(OS.NEWLINE)))
.toList();
List list = new ArrayList<>();
@@ -251,14 +253,14 @@ public List performSearch(BaseQueryNode queryNode) throws FetcherExcep
return list;
}
- private BufferedReader getInputStream(String urlString) {
+ private Optional getInputStream(String urlString) {
try {
URL url = URLUtil.create(urlString);
- return new BufferedReader(new InputStreamReader(url.openStream()));
+ return Optional.of(new BufferedReader(new InputStreamReader(url.openStream())));
} catch (IOException e) {
LOGGER.debug("Wrong URL", e);
+ return Optional.empty();
}
- return null;
}
@Override
diff --git a/jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java b/jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java
index d031935936b..0f3661f6c09 100644
--- a/jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java
+++ b/jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java
@@ -32,6 +32,7 @@
import org.jabref.model.study.Study;
import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,9 +63,12 @@ public class BibDatabaseContext {
/**
* The path where this database was last saved to.
*/
+ @Nullable
private Path path;
+ @Nullable
private DatabaseSynchronizer dbmsSynchronizer;
+ @Nullable
private CoarseChangeFilter dbmsListener;
private DatabaseLocation location;
@@ -223,10 +227,15 @@ private Path getFileDirectoryPath(String directory) {
// If this path is relative, we try to interpret it as relative to the file path of this BIB file:
return getDatabasePath()
- .map(databaseFile -> databaseFile.getParent().resolve(path).normalize().toAbsolutePath())
+ .map(databaseFile -> Optional.ofNullable(databaseFile.getParent())
+ .orElse(Path.of(""))
+ .resolve(path)
+ .normalize()
+ .toAbsolutePath())
.orElse(path);
}
+ @Nullable
public DatabaseSynchronizer getDBMSSynchronizer() {
return this.dbmsSynchronizer;
}
@@ -250,7 +259,9 @@ public void convertToSharedDatabase(DatabaseSynchronizer dmbsSynchronizer) {
public void convertToLocalDatabase() {
if (dbmsListener != null && (location == DatabaseLocation.SHARED)) {
- dbmsListener.unregisterListener(dbmsSynchronizer);
+ if (dbmsSynchronizer != null) {
+ dbmsListener.unregisterListener(dbmsSynchronizer);
+ }
dbmsListener.shutdown();
}
diff --git a/jablib/src/main/java/org/jabref/model/entry/field/StandardField.java b/jablib/src/main/java/org/jabref/model/entry/field/StandardField.java
index de6ff851511..5b7c3cad725 100644
--- a/jablib/src/main/java/org/jabref/model/entry/field/StandardField.java
+++ b/jablib/src/main/java/org/jabref/model/entry/field/StandardField.java
@@ -8,7 +8,8 @@
import java.util.Set;
/// Standard BibTeX and BibLaTeX fields, as well as "normal" JabRef specific fields.
-/// See `org.jabref.gui.fieldeditors.FieldNameLabel#getDescription(org.jabref.model.entry.field.Field)` for a description of each field.
+/// See [org.jabref.model.entry.field.FieldTextMapper] for the display name creation.
+/// See [org.jabref.gui.fieldeditors.FieldNameLabel#getDescription(org.jabref.model.entry.field.Field)] for a description of each field.
public enum StandardField implements Field {
ABSTRACT("abstract", FieldProperty.MULTILINE_TEXT),
ADDENDUM("addendum"),
@@ -34,7 +35,7 @@ public enum StandardField implements Field {
DATE("date", FieldProperty.DATE),
DAY("day"),
DAYFILED("dayfiled"),
- DOI("doi", "DOI", FieldProperty.VERBATIM, FieldProperty.IDENTIFIER),
+ DOI("doi", FieldProperty.VERBATIM, FieldProperty.IDENTIFIER),
EDITION("edition", FieldProperty.NUMERIC),
EDITOR("editor", FieldProperty.PERSON_NAMES),
EDITORA("editora", FieldProperty.PERSON_NAMES),
@@ -64,9 +65,9 @@ public enum StandardField implements Field {
IDS("ids", FieldProperty.MULTIPLE_ENTRY_LINK),
INSTITUTION("institution"),
INTRODUCTION("introduction", FieldProperty.PERSON_NAMES),
- ISBN("isbn", "ISBN", FieldProperty.VERBATIM),
- ISRN("isrn", "ISRN", FieldProperty.VERBATIM),
- ISSN("issn", "ISSN", FieldProperty.VERBATIM),
+ ISBN("isbn", FieldProperty.VERBATIM),
+ ISRN("isrn", FieldProperty.VERBATIM),
+ ISSN("issn", FieldProperty.VERBATIM),
ISSUE("issue"),
ISSUETITLE("issuetitle"),
ISSUESUBTITLE("issuesubtitle"),
@@ -96,9 +97,9 @@ public enum StandardField implements Field {
PAGETOTAL("pagetotal", FieldProperty.NUMERIC),
PAGINATION("pagination", FieldProperty.PAGINATION),
PART("part"),
- PDF("pdf", "PDF"),
- PMID("pmid", "PMID", FieldProperty.NUMERIC, FieldProperty.IDENTIFIER),
- PS("ps", "PS"),
+ PDF("pdf"),
+ PMID("pmid", FieldProperty.NUMERIC, FieldProperty.IDENTIFIER),
+ PS("ps"),
PUBLISHER("publisher"),
PUBSTATE("pubstate"),
PRIMARYCLASS("primaryclass"),
@@ -118,8 +119,8 @@ public enum StandardField implements Field {
TITLEADDON("titleaddon"),
TRANSLATOR("translator", FieldProperty.PERSON_NAMES),
TYPE("type"),
- URI("uri", "URI", FieldProperty.EXTERNAL, FieldProperty.VERBATIM),
- URL("url", "URL", FieldProperty.EXTERNAL, FieldProperty.VERBATIM),
+ URI("uri", FieldProperty.EXTERNAL, FieldProperty.VERBATIM),
+ URL("url", FieldProperty.EXTERNAL, FieldProperty.VERBATIM),
URLDATE("urldate", FieldProperty.DATE),
VENUE("venue"),
VERSION("version"),
@@ -152,7 +153,6 @@ public enum StandardField implements Field {
private static final Map NAME_TO_STANDARD_FIELD = new HashMap<>();
private final String name;
- private final String displayName;
private final EnumSet properties;
static {
@@ -163,25 +163,11 @@ public enum StandardField implements Field {
StandardField(String name) {
this.name = name;
- this.displayName = null;
this.properties = EnumSet.noneOf(FieldProperty.class);
}
- StandardField(String name, String displayName) {
- this.name = name;
- this.displayName = displayName;
- this.properties = EnumSet.noneOf(FieldProperty.class);
- }
-
- StandardField(String name, String displayName, FieldProperty first, FieldProperty... rest) {
- this.name = name;
- this.displayName = displayName;
- this.properties = EnumSet.of(first, rest);
- }
-
StandardField(String name, FieldProperty first, FieldProperty... rest) {
this.name = name;
- this.displayName = null;
this.properties = EnumSet.of(first, rest);
}