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..2c6c2b85459 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 @@ -125,7 +125,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, new EmbeddingRecord(null, "", new float[0])); 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..68cb4865586 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 @@ -34,7 +34,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 +64,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 +96,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 +118,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 +152,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 +162,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); }