diff --git a/.github/workflows/assign-issue.yml b/.github/workflows/assign-issue.yml index 07450aec692..7b1a9ac13bd 100644 --- a/.github/workflows/assign-issue.yml +++ b/.github/workflows/assign-issue.yml @@ -19,7 +19,7 @@ jobs: uses: takanome-dev/assign-issue-action@beta with: github_token: '${{ secrets.GITHUB_TOKEN }}' - days_until_unassign: 30 + days_until_unassign: 90 maintainers: koppor, Siedlerchr, ThiloteE, calixtus, HoussemNasri assigned_comment: | 👋 Hey @{{ handle }}, thank you for your interest in this issue! 🎉 diff --git a/.github/workflows/cleanup-pr.yml b/.github/workflows/cleanup-pr.yml index a4caf50b257..490443b0460 100644 --- a/.github/workflows/cleanup-pr.yml +++ b/.github/workflows/cleanup-pr.yml @@ -29,7 +29,7 @@ jobs: BUILDJABREFPRIVATEKEY: ${{ secrets.buildJabRefPrivateKey }} - name: Delete folder on builds.jabref.org if: steps.checksecrets.outputs.secretspresent == 'YES' - uses: appleboy/ssh-action@v1.1.0 + uses: appleboy/ssh-action@v1.2.0 with: script: rm -rf /var/www/builds.jabref.org/www/pull/${{ github.event.pull_request.number }} || true host: build-upload.jabref.org diff --git a/.github/workflows/deployment-arm64.yml b/.github/workflows/deployment-arm64.yml index b2d795d313d..8b26386157d 100644 --- a/.github/workflows/deployment-arm64.yml +++ b/.github/workflows/deployment-arm64.yml @@ -69,12 +69,12 @@ jobs: submodules: 'true' show-progress: 'false' - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v3.0.0 + uses: gittools/actions/gitversion/setup@v3.0.3 with: versionSpec: "5.x" - name: Run GitVersion id: gitversion - uses: gittools/actions/gitversion/execute@v3.0.0 + uses: gittools/actions/gitversion/execute@v3.0.3 - name: Setup JDK uses: actions/setup-java@v4 with: diff --git a/.github/workflows/deployment-jdk-ea.yml b/.github/workflows/deployment-jdk-ea.yml index 8cdf1e63e1e..799b6c569c7 100644 --- a/.github/workflows/deployment-jdk-ea.yml +++ b/.github/workflows/deployment-jdk-ea.yml @@ -85,12 +85,12 @@ jobs: packages: pigz version: 1.0 - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v3.0.0 + uses: gittools/actions/gitversion/setup@v3.0.3 with: versionSpec: "5.x" - name: Run GitVersion id: gitversion - uses: gittools/actions/gitversion/execute@v3.0.0 + uses: gittools/actions/gitversion/execute@v3.0.3 # JDK - name: 'Set up JDK ${{ matrix.jdk }}' diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 543ce7057dc..b0411f93902 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -81,12 +81,12 @@ jobs: packages: pigz version: 1.0 - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v3.0.0 + uses: gittools/actions/gitversion/setup@v3.0.3 with: versionSpec: "5.x" - name: Run GitVersion id: gitversion - uses: gittools/actions/gitversion/execute@v3.0.0 + uses: gittools/actions/gitversion/execute@v3.0.3 - name: Setup JDK uses: actions/setup-java@v4 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5907a2aef9b..78f8bdd5c5f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -109,7 +109,7 @@ jobs: submodules: 'false' show-progress: 'false' - name: markdownlint-cli2-action - uses: DavidAnson/markdownlint-cli2-action@v17 + uses: DavidAnson/markdownlint-cli2-action@v18 with: globs: | *.md @@ -322,7 +322,7 @@ jobs: CI: "true" CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} DBMS: "postgresql" - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 if: (github.ref == 'refs/heads/main') && (steps.checksecrets.outputs.secretspresent == 'YES') with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.moderne/moderne.yml b/.moderne/moderne.yml new file mode 100644 index 00000000000..e90c2b39622 --- /dev/null +++ b/.moderne/moderne.yml @@ -0,0 +1,3 @@ +specs: specs.moderne.ai/v1/cli +java: + selectedJdk: '23' diff --git a/CHANGELOG.md b/CHANGELOG.md index 2921d7cc0dd..0cc4fbe4094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added +- We added a Markdown export layout. [#12220](https://github.com/JabRef/jabref/pull/12220) - We added a "view as BibTeX" option before importing an entry from the citation relation tab. [#11826](https://github.com/JabRef/jabref/issues/11826) - We added support finding LaTeX-encoded special characters based on plain Unicode and vice versa. [#11542](https://github.com/JabRef/jabref/pull/11542) - When a search hits a file, the file icon of that entry is changed accordingly. [#11542](https://github.com/JabRef/jabref/pull/11542) @@ -43,8 +44,10 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076) - We added support to automatically open a `.bib` file in the current/parent folder if no other library is opened. [koppor#377](https://github.com/koppor/jabref/issues/377) - We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686) +- We added new modifiers `camel_case`, `camel_case_n`, `short_title`, and `very_short_title` for the [citation key generator](https://docs.jabref.org/setup/citationkeypatterns). [#11367](https://github.com/JabRef/jabref/issues/11367) - By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955) - We use the menu icon for background tasks as a progress indicator to visualise an import's progress when dragging and dropping several PDF files into the main table. [#12072](https://github.com/JabRef/jabref/pull/12072) +- The PDF content importer now supports importing title from upto the second page of the PDF. [#12139](https://github.com/JabRef/jabref/issues/12139) ### Changed @@ -76,6 +79,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We changed the name of the library-based file directory from 'General File Directory' to 'Library-specific File Directory' per issue. [#571](https://github.com/koppor/jabref/issues/571) - We changed the defualt [unwanted charachters](https://docs.jabref.org/setup/citationkeypatterns#removing-unwanted-characters) in the citation key generator and allow a dash (`-`) and colon (`:`) being part of a citation key. [#12144](https://github.com/JabRef/jabref/pull/12144) - The CitationKey column is now a default shown column for the entry table. [#10510](https://github.com/JabRef/jabref/issues/10510) +- We disabled the actions "Open Terminal here" and "Reveal in file explorer" for unsaved libraries. [#11920](https://github.com/JabRef/jabref/issues/11920) +- JabRef now opens the corresponding directory in the library properties when "Browse" is clicked. [#12223](https://github.com/JabRef/jabref/pull/12223) ### Fixed @@ -112,11 +117,13 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed an issue where the "Do not ask again" checkbox was not working, when asking for permission to use Grobid [koppor#556](https://github.com/koppor/jabref/issues/566). - We fixed an issue where we display warning message for moving attached open files. [#10121](https://github.com/JabRef/jabref/issues/10121) - We fixed an issue where it was not possible to select selecting content of other user's comments.[#11106](https://github.com/JabRef/jabref/issues/11106) +- We fixed an issue when handling URLs containing a pipe (`|`) character. [#11876](https://github.com/JabRef/jabref/issues/11876) - We fixed an issue where web search preferences "Custom API key" table modifications not discarded. [#11925](https://github.com/JabRef/jabref/issues/11925) - We fixed an issue when opening attached files in [extra file columns](https://docs.jabref.org/finding-sorting-and-cleaning-entries/filelinks#adding-additional-columns-to-entry-table-for-file-types). [#12005](https://github.com/JabRef/jabref/issues/12005) - We fixed an issue where trying to open a library from a failed mounted directory on Mac would cause an error. [#10548](https://github.com/JabRef/jabref/issues/10548) - We fixed an issue when the preview was out of sync. [#9172](https://github.com/JabRef/jabref/issues/9172) - We fixed an issue where identifier paste couldn't work with Unicode REPLACEMENT CHARACTER. [#11986](https://github.com/JabRef/jabref/issues/11986) +- We fixed an issue when click on entry at "Check Integrity" wasn't properly focusing the entry and field. [#11997](https://github.com/JabRef/jabref/issues/11997) ### Removed diff --git a/build.gradle b/build.gradle index 1a08fd86ef8..7b5d4c9a821 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ plugins { id 'idea' - id 'org.openrewrite.rewrite' version '6.27.0' + id 'org.openrewrite.rewrite' version '6.27.2' id "org.itsallcode.openfasttrace" version "3.0.1" } @@ -54,13 +54,14 @@ java { toolchain { // If this is updated, also update - // - .gitpod.Dockerfile + // - build.gradle -> jacoco -> toolVersion (because JaCoCo does not support newest JDK out of the box. Check versions at https://www.jacoco.org/jacoco/trunk/doc/changes.html) // - .devcontainer/devcontainer.json#L34 and + // - .gitpod.Dockerfile + // - .moderne/moderne.yml // - .github/workflows/deployment*.yml // - .github/workflows/tests*.yml // - .github/workflows/update-gradle-wrapper.yml // - docs/getting-into-the-code/guidelines-for-setting-up-a-local-workspace/intellij-12-build.md - // - build.gradle -> jacoco -> toolVersion (because JaCoCo does not support newest JDK out of the box. Check versions at https://www.jacoco.org/jacoco/trunk/doc/changes.html) languageVersion = JavaLanguageVersion.of(23) // See https://docs.gradle.org/current/javadoc/org/gradle/jvm/toolchain/JvmVendorSpec.html for a full list // vendor = JvmVendorSpec.AMAZON @@ -265,7 +266,7 @@ dependencies { // region HTTP clients implementation 'org.jsoup:jsoup:1.18.1' - implementation 'com.konghq:unirest-java-core:4.4.4' + implementation 'com.konghq:unirest-java-core:4.4.5' implementation 'com.konghq:unirest-modules-gson:4.4.5' implementation 'org.apache.httpcomponents.client5:httpclient5:5.4' // endregion @@ -278,7 +279,7 @@ dependencies { // route all requests to java.util.logging to SLF4J (which in turn routes to tinylog) implementation 'org.slf4j:jul-to-slf4j:2.0.16' // route all requests to log4j to SLF4J - implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.24.1' + implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.24.2' implementation('de.undercouch:citeproc-java:3.1.0') { exclude group: 'org.antlr' @@ -334,23 +335,23 @@ dependencies { implementation 'org.yaml:snakeyaml:2.3' // region AI - implementation 'dev.langchain4j:langchain4j:0.35.0' + implementation 'dev.langchain4j:langchain4j:0.36.0' // Even though we use jvm-openai for LLM connection, we still need this package for tokenization. - implementation('dev.langchain4j:langchain4j-open-ai:0.35.0') { + implementation('dev.langchain4j:langchain4j-open-ai:0.36.0') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' exclude group: 'org.jetbrains.kotlin' } - implementation('dev.langchain4j:langchain4j-mistral-ai:0.35.0') { + implementation('dev.langchain4j:langchain4j-mistral-ai:0.36.2') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' exclude group: 'org.jetbrains.kotlin' } - implementation('dev.langchain4j:langchain4j-google-ai-gemini:0.35.0') { + implementation('dev.langchain4j:langchain4j-google-ai-gemini:0.36.0') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' } - implementation('dev.langchain4j:langchain4j-hugging-face:0.35.0') { + implementation('dev.langchain4j:langchain4j-hugging-face:0.36.0') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' exclude group: 'org.jetbrains.kotlin' @@ -370,17 +371,17 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21' // endregion - implementation 'commons-io:commons-io:2.17.0' + implementation 'commons-io:commons-io:2.18.0' // Even if "compileOnly" is used, IntelliJ always adds to module-info.java. To avoid issues during committing, we use "implementation" instead of "compileOnly" implementation 'io.github.adr:e-adr:2.0.0-SNAPSHOT' - implementation 'io.zonky.test:embedded-postgres:2.0.7' + implementation 'io.zonky.test:embedded-postgres:2.1.0' implementation enforcedPlatform('io.zonky.test.postgres:embedded-postgres-binaries-bom:17.0.0') testImplementation 'io.github.classgraph:classgraph:4.8.177' - testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0' - testImplementation 'org.junit.platform:junit-platform-launcher:1.10.3' + testImplementation 'org.junit.jupiter:junit-jupiter:5.11.3' + testImplementation 'org.junit.platform:junit-platform-launcher:1.11.3' testImplementation 'org.mockito:mockito-core:5.14.2' testImplementation 'org.xmlunit:xmlunit-core:2.10.0' @@ -393,14 +394,14 @@ dependencies { testImplementation "com.github.javaparser:javaparser-symbol-solver-core:3.26.2" // recommended by https://github.com/wiremock/wiremock/issues/2149#issuecomment-1835775954 - testImplementation 'org.wiremock:wiremock-standalone:3.3.1' + testImplementation 'org.wiremock:wiremock-standalone:3.9.2' checkstyle 'com.puppycrawl.tools:checkstyle:10.20.1' // xjc needs the runtime as well for the ant task, otherwise it fails xjc group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: '3.0.2' xjc group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '3.0.2' - rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:2.19.0")) + rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:2.22.0")) rewrite("org.openrewrite.recipe:rewrite-static-analysis") rewrite("org.openrewrite.recipe:rewrite-logging-frameworks") rewrite("org.openrewrite.recipe:rewrite-testing-frameworks") diff --git a/config/IntelliJ Code Style.xml b/config/IntelliJ Code Style.xml index 6a03e104d9d..51aa18498d7 100644 --- a/config/IntelliJ Code Style.xml +++ b/config/IntelliJ Code Style.xml @@ -293,4 +293,4 @@ - \ No newline at end of file + diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index b40e6b25d37..312e52aca6e 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -33,6 +33,13 @@ + + + + + + + diff --git a/config/checkstyle/checkstyle_reviewdog.xml b/config/checkstyle/checkstyle_reviewdog.xml index 510baff905f..13f380bad61 100644 --- a/config/checkstyle/checkstyle_reviewdog.xml +++ b/config/checkstyle/checkstyle_reviewdog.xml @@ -33,6 +33,13 @@ + + + + + + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fb602ee2af0..eb1a55be0e1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=31c55713e40233a8303827ceb42ca48a47267a0ad4bab9177123121e71524c26 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionSha256Sum=f397b287023acdba1e9f6fc5ea72d22dd63669d59ed4a289a29b1a76eee151c6 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index 208e91dacb2..f93ef8c6101 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -941,8 +941,7 @@ public void pasteEntry() { private List handleNonBibTeXStringData(String data) { try { return this.importHandler.handleStringData(data); - } catch ( - FetcherException exception) { + } catch (FetcherException exception) { if (exception instanceof FetcherClientException) { dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("No data was found for the identifier")); } else if (exception instanceof FetcherServerException) { diff --git a/src/main/java/org/jabref/gui/actions/ActionHelper.java b/src/main/java/org/jabref/gui/actions/ActionHelper.java index 437d38d9bfe..16ffd8050c5 100644 --- a/src/main/java/org/jabref/gui/actions/ActionHelper.java +++ b/src/main/java/org/jabref/gui/actions/ActionHelper.java @@ -29,6 +29,11 @@ public static BooleanExpression needsDatabase(StateManager stateManager) { return stateManager.activeDatabaseProperty().isPresent(); } + public static BooleanExpression needsSavedLocalDatabase(StateManager stateManager) { + EasyBinding binding = EasyBind.map(stateManager.activeDatabaseProperty(), context -> context.filter(c -> c.getLocation() == DatabaseLocation.LOCAL && c.getDatabasePath().isPresent()).isPresent()); + return BooleanExpression.booleanExpression(binding); + } + public static BooleanExpression needsSharedDatabase(StateManager stateManager) { EasyBinding binding = EasyBind.map(stateManager.activeDatabaseProperty(), context -> context.filter(c -> c.getLocation() == DatabaseLocation.SHARED).isPresent()); return BooleanExpression.booleanExpression(binding); @@ -49,7 +54,7 @@ public static BooleanExpression needsEntriesSelected(StateManager stateManager) public static BooleanExpression needsEntriesSelected(int numberOfEntries, StateManager stateManager) { return Bindings.createBooleanBinding(() -> stateManager.getSelectedEntries().size() == numberOfEntries, - stateManager.getSelectedEntries()); + stateManager.getSelectedEntries()); } public static BooleanExpression isFieldSetForSelectedEntry(Field field, StateManager stateManager) { diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 3a2bd6f2258..ab1bb640dfe 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -13,6 +13,7 @@ import java.util.SortedSet; import java.util.stream.Collectors; +import javafx.application.Platform; import javafx.fxml.FXML; import javafx.geometry.Side; import javafx.scene.control.Button; @@ -61,6 +62,7 @@ import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.model.entry.EntryConverter; import org.jabref.model.entry.field.Field; import org.jabref.model.util.DirectoryMonitorManager; import org.jabref.model.util.FileUpdateMonitor; @@ -463,11 +465,26 @@ private void fetchAndMerge(EntryBasedFetcher fetcher) { public void setFocusToField(Field field) { UiTaskExecutor.runInJavaFXThread(() -> { + Field actualField = field; + boolean fieldFound = false; for (Tab tab : tabbed.getTabs()) { + tabbed.getSelectionModel().select(tab); if ((tab instanceof FieldsEditorTab fieldsEditorTab) - && fieldsEditorTab.getShownFields().contains(field)) { + && fieldsEditorTab.getShownFields().contains(actualField)) { tabbed.getSelectionModel().select(tab); - fieldsEditorTab.requestFocus(field); + Platform.runLater(() -> { + fieldsEditorTab.requestFocus(actualField); + }); + // This line explicitly brings focus back to the main window containing the Entry Editor. + getScene().getWindow().requestFocus(); + fieldFound = true; + break; + } + } + if (!fieldFound) { + Field aliasField = EntryConverter.FIELD_ALIASES.get(field); + if (aliasField != null) { + setFocusToField(aliasField); } } }); diff --git a/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java b/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java index eec4567e718..39cfdf8ff89 100644 --- a/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java @@ -251,7 +251,7 @@ private void addPreviewPanel() { public void removePreviewPanelFromThisTab() { assert this.getContent() instanceof SplitPane; - if (this.getContent() instanceof SplitPane splitPane && splitPane.getItems().contains(previewPanel)) { + if (this.getContent() instanceof SplitPane splitPane) { splitPane.getItems().remove(previewPanel); // Needed to "redraw" the split pane with one item (because JavaFX does not readjust if it is shown) // splitPane.setDividerPositions(1.0); @@ -260,10 +260,10 @@ public void removePreviewPanelFromThisTab() { @Override protected void handleFocus() { - LOGGER.error("This is {}", preferences.getPreviewPreferences().showPreviewAsExtraTabProperty().get()); - LOGGER.error("This is then {}", !preferences.getPreviewPreferences().showPreviewAsExtraTabProperty().get()); + LOGGER.trace("This is {}", preferences.getPreviewPreferences().showPreviewAsExtraTabProperty().get()); + LOGGER.trace("This is then {}", !preferences.getPreviewPreferences().showPreviewAsExtraTabProperty().get()); if (!preferences.getPreviewPreferences().showPreviewAsExtraTabProperty().get()) { - LOGGER.error("Focus on preview panel"); + LOGGER.trace("Focus on preview panel"); // We need to move the preview panel from the non-visible tab to the visible tab removePreviewPanelFromOtherTabs(); diff --git a/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java b/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java index 3267ed44f31..c085fbc50bd 100644 --- a/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java +++ b/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/semanticscholar/SemanticScholarFetcher.java @@ -1,7 +1,6 @@ package org.jabref.gui.entryeditor.citationrelationtab.semanticscholar; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.util.List; @@ -9,6 +8,7 @@ import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.fetcher.CustomizableKeyFetcher; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import com.google.gson.Gson; @@ -38,7 +38,7 @@ public List searchCitedBy(BibEntry entry) throws FetcherException { URL citationsUrl; try { - citationsUrl = URI.create(getAPIUrl("citations", entry)).toURL(); + citationsUrl = URLUtil.create(getAPIUrl("citations", entry)); } catch (MalformedURLException e) { throw new FetcherException("Malformed URL", e); } @@ -62,7 +62,7 @@ public List searchCiting(BibEntry entry) throws FetcherException { URL referencesUrl; try { - referencesUrl = URI.create(getAPIUrl("references", entry)).toURL(); + referencesUrl = URLUtil.create(getAPIUrl("references", entry)); } catch (MalformedURLException e) { throw new FetcherException("Malformed URL", e); } diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java index ea30f18d3c9..96c00de9f3b 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java @@ -287,7 +287,7 @@ public Parent getNode() { @FXML private void addNewFile() { - dialogService.showCustomDialogAndWait(new LinkedFileEditDialog()).ifPresent(newLinkedFile -> { + dialogService.showCustomDialogAndWait(new LinkedFileEditDialog()).filter(file -> !file.isEmpty()).ifPresent(newLinkedFile -> { viewModel.addNewLinkedFile(newLinkedFile); }); } diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java index 540e5603d36..b5c488750ad 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java @@ -2,9 +2,7 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -32,7 +30,6 @@ import org.jabref.gui.linkedfile.AttachFileFromURLAction; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.BindingsHelper; -import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.bibtex.FileFieldWriter; import org.jabref.logic.importer.FulltextFetchers; import org.jabref.logic.importer.util.FileFieldParser; @@ -40,7 +37,7 @@ import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.BackgroundTask; import org.jabref.logic.util.TaskExecutor; -import org.jabref.logic.util.io.FileNameCleaner; +import org.jabref.logic.util.URLUtil; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -107,19 +104,6 @@ public static LinkedFile fromFile(Path file, List fileDirectories, Externa return new LinkedFile("", relativePath, suggestedFileType.getName()); } - public LinkedFileViewModel fromFile(Path file, ExternalApplicationsPreferences externalApplicationsPreferences) { - List fileDirectories = databaseContext.getFileDirectories(preferences.getFilePreferences()); - - LinkedFile linkedFile = fromFile(file, fileDirectories, externalApplicationsPreferences); - return new LinkedFileViewModel( - linkedFile, - entry, - databaseContext, - taskExecutor, - dialogService, - preferences); - } - private List parseToFileViewModel(String stringValue) { return FileFieldParser.parse(stringValue).stream() .map(linkedFile -> new LinkedFileViewModel( @@ -140,41 +124,6 @@ public ListProperty filesProperty() { return files; } - public void addNewFile() { - Path workingDirectory = databaseContext.getFirstExistingFileDir(preferences.getFilePreferences()) - .orElse(preferences.getFilePreferences().getWorkingDirectory()); - - FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() - .withInitialDirectory(workingDirectory) - .build(); - - List fileDirectories = databaseContext.getFileDirectories(preferences.getFilePreferences()); - List selectedFiles = dialogService.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration); - - for (Path fileToAdd : selectedFiles) { - if (FileUtil.detectBadFileName(fileToAdd.toString())) { - String newFilename = FileNameCleaner.cleanFileName(fileToAdd.getFileName().toString()); - - boolean correctButtonPressed = dialogService.showConfirmationDialogAndWait(Localization.lang("File \"%0\" cannot be added!", fileToAdd.getFileName()), - Localization.lang("Illegal characters in the file name detected.\nFile will be renamed to \"%0\" and added.", newFilename), - Localization.lang("Rename and add")); - - if (correctButtonPressed) { - Path correctPath = fileToAdd.resolveSibling(newFilename); - try { - Files.move(fileToAdd, correctPath); - addNewLinkedFile(correctPath, fileDirectories); - } catch (IOException ex) { - LOGGER.error("Error moving file", ex); - dialogService.showErrorDialogAndWait(ex); - } - } - } else { - addNewLinkedFile(fileToAdd, fileDirectories); - } - } - } - public void addNewLinkedFile(LinkedFile linkedFile) { files.add(new LinkedFileViewModel( linkedFile, @@ -185,22 +134,17 @@ public void addNewLinkedFile(LinkedFile linkedFile) { preferences)); } - private void addNewLinkedFile(Path correctPath, List fileDirectories) { - LinkedFile newLinkedFile = fromFile(correctPath, fileDirectories, preferences.getExternalApplicationsPreferences()); - addNewLinkedFile(newLinkedFile); - } - @Override public void bindToEntry(BibEntry entry) { super.bindToEntry(entry); - if ((entry != null) && preferences.getEntryEditorPreferences().autoLinkFilesEnabled()) { + if (preferences.getEntryEditorPreferences().autoLinkFilesEnabled()) { LOGGER.debug("Auto-linking files for entry {}", entry); BackgroundTask> findAssociatedNotLinkedFiles = BackgroundTask .wrap(() -> findAssociatedNotLinkedFiles(entry)) .onSuccess(list -> { if (!list.isEmpty()) { - LOGGER.debug("Found non-associated files:", list); + LOGGER.debug("Found non-associated files: {}", list); files.addAll(list); } }); @@ -242,7 +186,7 @@ private List findAssociatedNotLinkedFiles(BibEntry entry) { public boolean downloadFile(String urlText) { try { - URL url = URI.create(urlText).toURL(); + URL url = URLUtil.create(urlText); addFromURLAndDownload(url); return true; } catch (MalformedURLException exception) { diff --git a/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java b/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java index c1a54103ac6..0278036032e 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java +++ b/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java @@ -1,89 +1,22 @@ package org.jabref.gui.fieldeditors; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.util.Objects; import java.util.Optional; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.frame.ExternalApplicationsPreferences; +/** + * URL utilities for URLs in the JabRef GUI. + *

+ * For logic-oriented URL utilities see {@link org.jabref.logic.util.URLUtil}. + */ public class URLUtil { - private static final String URL_EXP = "^(https?|ftp)://.+"; - - // Detect Google search URL - private static final String GOOGLE_SEARCH_EXP = "^https?://(?:www\\.)?google\\.[\\.a-z]+?/url.*"; private URLUtil() { } - /** - * Cleans URLs returned by Google search. - * - * - * If you copy links from search results from Google, all links will be enriched with search meta data, e.g. - * https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&&url=http%3A%2F%2Fwww.inrg.csie.ntu.edu.tw%2Falgorithm2014%2Fhomework%2FWagner-74.pdf&ei=DifeVYHkDYWqU5W0j6gD&usg=AFQjCNFl638rl5KVta1jIMWLyb4CPSZidg&sig2=0hSSMw9XZXL3HJWwEcJtOg - * - * - * @param url the Google search URL string - * @return the cleaned Google URL or @code{url} if no search URL was detected - */ - public static String cleanGoogleSearchURL(String url) { - Objects.requireNonNull(url); - - if (!url.matches(GOOGLE_SEARCH_EXP)) { - return url; - } - // Extract destination URL - try { - URL searchURL = URI.create(url).toURL(); - // URL parameters - String query = searchURL.getQuery(); - // no parameters - if (query == null) { - return url; - } - // extract url parameter - String[] pairs = query.split("&"); - - for (String pair : pairs) { - // "clean" url is decoded value of "url" parameter - if (pair.startsWith("url=")) { - String value = pair.substring(pair.indexOf('=') + 1); - - String decode = URLDecoder.decode(value, StandardCharsets.UTF_8); - // url? - if (decode.matches(URL_EXP)) { - return decode; - } - } - } - return url; - } catch (MalformedURLException e) { - return url; - } - } - - /** - * Checks whether the given String is a URL. - *

- * Currently only checks for a protocol String. - * - * @param url the String to check for a URL - * @return true if url contains a valid URL - */ - public static boolean isURL(String url) { - try { - URI.create(url).toURL(); - return true; - } catch (MalformedURLException | IllegalArgumentException e) { - return false; - } - } - /** * Look for the last '.' in the link, and return the following characters. *

@@ -96,7 +29,7 @@ public static Optional getSuffix(final String link, ExternalApplications String strippedLink = link; try { // Try to strip the query string, if any, to get the correct suffix: - URL url = URI.create(link).toURL(); + URL url = org.jabref.logic.util.URLUtil.create(link); if ((url.getQuery() != null) && (url.getQuery().length() < (link.length() - 1))) { strippedLink = link.substring(0, link.length() - url.getQuery().length() - 1); } diff --git a/src/main/java/org/jabref/gui/fieldeditors/UrlEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/UrlEditorViewModel.java index dceea6a5265..85f05a5c164 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/UrlEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/UrlEditorViewModel.java @@ -13,6 +13,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.logic.integrity.FieldCheckers; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.field.Field; import org.jabref.model.strings.StringUtil; diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index a57d4026dbc..01420aa6b71 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -64,6 +64,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.jabref.gui.actions.ActionHelper.needsSavedLocalDatabase; + /** * Represents the inner frame of the JabRef window */ @@ -79,7 +81,6 @@ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMe private final GlobalSearchBar globalSearchBar; private final FileHistoryMenu fileHistory; - private final FrameDndHandler frameDndHandler; @SuppressWarnings({"FieldCanBeLocal"}) private EasyObservableList openDatabaseList; @@ -136,7 +137,7 @@ public JabRefFrame(Stage mainStage, taskExecutor); Injector.setModelOrService(UiMessageHandler.class, viewModel); - this.frameDndHandler = new FrameDndHandler( + FrameDndHandler frameDndHandler = new FrameDndHandler( tabbedPane, mainStage::getScene, this::getOpenDatabaseAction, @@ -425,7 +426,7 @@ public void showLibraryTab(@NonNull LibraryTab libraryTab) { /** * Opens a new tab with existing data. * Asynchronous loading is done at {@link LibraryTab#createLibraryTab}. - * Similar method: {@link OpenDatabaseAction#openTheFile(Path)} + * Similar method: {@link OpenDatabaseAction#openTheFile(Path)} (Path)} */ public void addTab(@NonNull BibDatabaseContext databaseContext, boolean raisePanel) { Objects.requireNonNull(databaseContext); @@ -637,6 +638,7 @@ private class OpenDatabaseFolder extends SimpleCommand { public OpenDatabaseFolder(Supplier databaseContext) { this.databaseContext = databaseContext; + this.executable.bind(needsSavedLocalDatabase(stateManager)); } @Override diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java index bb80c46734b..afb86d06d70 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java @@ -309,11 +309,10 @@ private void openDatabases(List parserResults) { undoManager, clipBoardManager, taskExecutor); - } catch ( - SQLException | - DatabaseNotSupportedException | - InvalidDBMSConnectionPropertiesException | - NotASharedDatabaseException e) { + } catch (SQLException + | DatabaseNotSupportedException + | InvalidDBMSConnectionPropertiesException + | NotASharedDatabaseException e) { LOGGER.error("Connection error", e); dialogService.showErrorDialogAndWait( Localization.lang("Connection error"), diff --git a/src/main/java/org/jabref/gui/frame/OpenConsoleAction.java b/src/main/java/org/jabref/gui/frame/OpenConsoleAction.java index c29c86a5d02..c60451c37f0 100644 --- a/src/main/java/org/jabref/gui/frame/OpenConsoleAction.java +++ b/src/main/java/org/jabref/gui/frame/OpenConsoleAction.java @@ -35,7 +35,7 @@ public OpenConsoleAction(Supplier databaseContext, StateMana this.preferences = preferences; this.dialogService = dialogService; - this.executable.bind(ActionHelper.needsDatabase(stateManager)); + this.executable.bind(ActionHelper.needsSavedLocalDatabase(stateManager)); } /** diff --git a/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java b/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java index 2e28d8021fd..93edf244bd5 100644 --- a/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java +++ b/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java @@ -2,7 +2,9 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.Optional; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ListProperty; @@ -18,6 +20,7 @@ import org.jabref.gui.libraryproperties.PropertiesTabViewModel; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.l10n.Encodings; +import org.jabref.logic.l10n.Localization; import org.jabref.logic.preferences.CliPreferences; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.model.database.BibDatabaseContext; @@ -40,16 +43,12 @@ public class GeneralPropertiesViewModel implements PropertiesTabViewModel { private final BibDatabaseContext databaseContext; private final MetaData metaData; - private final DirectoryDialogConfiguration directoryDialogConfiguration; GeneralPropertiesViewModel(BibDatabaseContext databaseContext, DialogService dialogService, CliPreferences preferences) { this.dialogService = dialogService; this.preferences = preferences; this.databaseContext = databaseContext; this.metaData = databaseContext.getMetaData(); - - this.directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() - .withInitialDirectory(preferences.getFilePreferences().getWorkingDirectory()).build(); } @Override @@ -96,16 +95,22 @@ public void storeSettings() { } public void browseLibrarySpecificDir() { + DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() + .withInitialDirectory(getBrowseDirectory(librarySpecificDirectoryProperty.getValue())).build(); dialogService.showDirectorySelectionDialog(directoryDialogConfiguration) .ifPresent(dir -> librarySpecificDirectoryProperty.setValue(dir.toAbsolutePath().toString())); } public void browseUserDir() { + DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() + .withInitialDirectory(getBrowseDirectory(userSpecificFileDirectoryProperty.getValue())).build(); dialogService.showDirectorySelectionDialog(directoryDialogConfiguration) .ifPresent(dir -> userSpecificFileDirectoryProperty.setValue(dir.toAbsolutePath().toString())); } public void browseLatexDir() { + DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() + .withInitialDirectory(getBrowseDirectory(laTexFileDirectoryProperty.getValue())).build(); dialogService.showDirectorySelectionDialog(directoryDialogConfiguration) .ifPresent(dir -> laTexFileDirectoryProperty.setValue(dir.toAbsolutePath().toString())); } @@ -141,4 +146,19 @@ public StringProperty userSpecificFileDirectoryProperty() { public StringProperty laTexFileDirectoryProperty() { return this.laTexFileDirectoryProperty; } + + private Path getBrowseDirectory(String configuredDir) { + if (configuredDir.isEmpty()) { + return preferences.getFilePreferences().getWorkingDirectory(); + } + Optional foundPath = this.databaseContext.getFileDirectories(preferences.getFilePreferences()).stream() + .filter(path -> path.toString().endsWith(configuredDir)) + .filter(Files::exists).findFirst(); + + if (foundPath.isEmpty()) { + dialogService.notify(Localization.lang("Path %0 could not be resolved. Using working dir.", configuredDir)); + return preferences.getFilePreferences().getWorkingDirectory(); + } + return foundPath.get(); + } } diff --git a/src/main/java/org/jabref/gui/linkedfile/AttachFileFromURLAction.java b/src/main/java/org/jabref/gui/linkedfile/AttachFileFromURLAction.java index 61ec0f65ed4..8ac056f8119 100644 --- a/src/main/java/org/jabref/gui/linkedfile/AttachFileFromURLAction.java +++ b/src/main/java/org/jabref/gui/linkedfile/AttachFileFromURLAction.java @@ -1,7 +1,6 @@ package org.jabref.gui.linkedfile; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.util.Optional; @@ -14,6 +13,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; +import org.jabref.logic.util.URLUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; @@ -61,7 +61,7 @@ public void execute() { } try { - URL url = URI.create(urlforDownload.get()).toURL(); + URL url = URLUtil.create(urlforDownload.get()); LinkedFileViewModel onlineFile = new LinkedFileViewModel( new LinkedFile(url, ""), entry, diff --git a/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogViewModel.java b/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogViewModel.java index cd31283742c..c360fe6e90f 100644 --- a/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogViewModel.java +++ b/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogViewModel.java @@ -1,7 +1,8 @@ package org.jabref.gui.linkedfile; +import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Optional; import java.util.regex.Pattern; @@ -22,15 +23,23 @@ import org.jabref.gui.frame.ExternalApplicationsPreferences; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.FilePreferences; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.URLUtil; +import org.jabref.logic.util.io.FileNameCleaner; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.LinkedFile; +import com.google.common.annotations.VisibleForTesting; import com.tobiasdiez.easybind.EasyBind; import com.tobiasdiez.easybind.optional.ObservableOptionalValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class LinkedFileEditDialogViewModel extends AbstractViewModel { + private static final Logger LOGGER = LoggerFactory.getLogger(LinkedFileEditDialogViewModel.class); + private static final Pattern REMOTE_LINK_PATTERN = Pattern.compile("[a-z]+://.*"); private final StringProperty link = new SimpleStringProperty(""); private final StringProperty description = new SimpleStringProperty(""); @@ -86,13 +95,35 @@ public void openBrowseDialog() { .withInitialFileName(fileName) .build(); - dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(path -> { - // Store the directory for next time: - filePreferences.setWorkingDirectory(path); - link.set(relativize(path)); + dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(this::checkForBadFileNameAndAdd); + } + @VisibleForTesting + void checkForBadFileNameAndAdd(Path fileToAdd) { + if (FileUtil.detectBadFileName(fileToAdd.toString())) { + String newFilename = FileNameCleaner.cleanFileName(fileToAdd.getFileName().toString()); + + boolean correctButtonPressed = dialogService.showConfirmationDialogAndWait(Localization.lang("File \"%0\" cannot be added!", fileToAdd.getFileName()), + Localization.lang("Illegal characters in the file name detected.\nFile will be renamed to \"%0\" and added.", newFilename), + Localization.lang("Rename and add")); + + if (correctButtonPressed) { + Path correctPath = fileToAdd.resolveSibling(newFilename); + try { + Files.move(fileToAdd, correctPath); + link.set(relativize(correctPath)); + filePreferences.setWorkingDirectory(correctPath); + setExternalFileTypeByExtension(link.getValueSafe()); + } catch (IOException ex) { + LOGGER.error("Error moving file", ex); + dialogService.showErrorDialogAndWait(ex); + } + } + } else { + link.set(relativize(fileToAdd)); + filePreferences.setWorkingDirectory(fileToAdd); setExternalFileTypeByExtension(link.getValueSafe()); - }); + } } public void setValues(LinkedFile linkedFile) { @@ -139,7 +170,7 @@ public LinkedFile getNewLinkedFile() { if (LinkedFile.isOnlineLink(link.getValue())) { try { - return new LinkedFile(description.getValue(), URI.create(link.getValue()).toURL(), fileType, sourceUrl.getValue()); + return new LinkedFile(description.getValue(), URLUtil.create(link.getValue()), fileType, sourceUrl.getValue()); } catch (MalformedURLException e) { return new LinkedFile(description.getValue(), link.getValue(), fileType, sourceUrl.getValue()); } diff --git a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/cell/FieldValueCell.java b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/cell/FieldValueCell.java index d93b6d4f45f..68d90e0e2ea 100644 --- a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/cell/FieldValueCell.java +++ b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/cell/FieldValueCell.java @@ -20,10 +20,10 @@ import javafx.scene.paint.Color; import org.jabref.gui.actions.ActionFactory; -import org.jabref.gui.fieldeditors.URLUtil; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.identifier.DOI; import org.jabref.model.strings.StringUtil; diff --git a/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java b/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java index 82befda6b05..1cca1235fd4 100644 --- a/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java +++ b/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java @@ -138,8 +138,7 @@ public void editStyle() { Optional type = ExternalFileTypes.getExternalFileTypeByExt("jstyle", externalApplicationsPreferences); try { NativeDesktop.openExternalFileAnyFormat(new BibDatabaseContext(), externalApplicationsPreferences, filePreferences, jStyle.getPath(), type); - } catch ( - IOException e) { + } catch (IOException e) { dialogService.showErrorDialogAndWait(e); } } diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index 519b9899ed2..15dba31fdad 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -197,8 +197,7 @@ private void updateDirectoryWarning(Path directory) { } else { directoryWarning.setVisible(false); } - } catch ( - IOException e) { + } catch (IOException e) { directoryWarning.setText(Localization.lang("Warning: Failed to check if the directory is empty.")); directoryWarning.setVisible(true); } diff --git a/src/main/java/org/jabref/gui/theme/StyleSheetFile.java b/src/main/java/org/jabref/gui/theme/StyleSheetFile.java index 9401e51b18b..515f37854ed 100644 --- a/src/main/java/org/jabref/gui/theme/StyleSheetFile.java +++ b/src/main/java/org/jabref/gui/theme/StyleSheetFile.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.io.InputStream; -import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; @@ -11,6 +10,8 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; +import org.jabref.logic.util.URLUtil; + import com.google.common.base.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,7 +55,7 @@ final class StyleSheetFile extends StyleSheet { StyleSheetFile(URL url) { this.url = url; - this.path = Path.of(URI.create(url.toExternalForm())); + this.path = Path.of(URLUtil.createUri(url.toExternalForm())); reload(); } diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java index 20c26951f69..d83a31210a5 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/Gpt4AllModel.java @@ -1,6 +1,5 @@ package org.jabref.logic.ai.chatting.model; -import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; @@ -9,6 +8,7 @@ import java.util.stream.Collectors; import org.jabref.logic.ai.AiPreferences; +import org.jabref.logic.util.URLUtil; import com.google.gson.Gson; import dev.langchain4j.data.message.AiMessage; @@ -62,7 +62,7 @@ public Response generate(List list) { String baseUrl = aiPreferences.getSelectedApiBaseUrl(); String fullUrl = baseUrl.endsWith("/") ? baseUrl + "chat/completions" : baseUrl + "/chat/completions"; HttpRequest httpRequest = HttpRequest.newBuilder() - .uri(URI.create(fullUrl)) + .uri(URLUtil.createUri(fullUrl)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .timeout(Duration.ofSeconds(60)) diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 28a89ebfe7c..bcd6de20bef 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -43,6 +43,7 @@ public static ExporterFactory create(CliPreferences preferences) { exporters.add(new TemplateExporter(Localization.lang("HTML table"), "tablerefs", "tablerefs", "tablerefs", StandardFileType.HTML, layoutPreferences, saveOrder)); exporters.add(new TemplateExporter(Localization.lang("HTML list"), "listrefs", "listrefs", "listrefs", StandardFileType.HTML, layoutPreferences, saveOrder)); exporters.add(new TemplateExporter(Localization.lang("HTML table (with Abstract & BibTeX)"), "tablerefsabsbib", "tablerefsabsbib", "tablerefsabsbib", StandardFileType.HTML, layoutPreferences, saveOrder)); + exporters.add(new TemplateExporter(Localization.lang("Markdown titles"), "title-md", "title-md", "title-markdown", StandardFileType.MARKDOWN, layoutPreferences, saveOrder)); exporters.add(new TemplateExporter("Harvard RTF", "harvard", "harvard", "harvard", StandardFileType.RTF, layoutPreferences, saveOrder)); exporters.add(new TemplateExporter("ISO 690 RTF", "iso690rtf", "iso690RTF", "iso690rtf", StandardFileType.RTF, layoutPreferences, saveOrder)); exporters.add(new TemplateExporter("ISO 690", "iso690txt", "iso690", "iso690txt", StandardFileType.TXT, layoutPreferences, saveOrder)); diff --git a/src/main/java/org/jabref/logic/formatter/Formatters.java b/src/main/java/org/jabref/logic/formatter/Formatters.java index fb827f9ab8e..a52c4437848 100644 --- a/src/main/java/org/jabref/logic/formatter/Formatters.java +++ b/src/main/java/org/jabref/logic/formatter/Formatters.java @@ -30,12 +30,16 @@ import org.jabref.logic.formatter.bibtexfields.ShortenDOIFormatter; import org.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter; import org.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; +import org.jabref.logic.formatter.casechanger.CamelFormatter; +import org.jabref.logic.formatter.casechanger.CamelNFormatter; import org.jabref.logic.formatter.casechanger.CapitalizeFormatter; import org.jabref.logic.formatter.casechanger.LowerCaseFormatter; import org.jabref.logic.formatter.casechanger.SentenceCaseFormatter; +import org.jabref.logic.formatter.casechanger.ShortTitleFormatter; import org.jabref.logic.formatter.casechanger.TitleCaseFormatter; import org.jabref.logic.formatter.casechanger.UnprotectTermsFormatter; import org.jabref.logic.formatter.casechanger.UpperCaseFormatter; +import org.jabref.logic.formatter.casechanger.VeryShortTitleFormatter; import org.jabref.logic.formatter.minifier.MinifyNameListFormatter; import org.jabref.logic.formatter.minifier.TruncateFormatter; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; @@ -96,11 +100,20 @@ public static List getOthers() { ); } + public static List getTitleChangers() { + return Arrays.asList( + new VeryShortTitleFormatter(), + new ShortTitleFormatter(), + new CamelFormatter() + ); + } + public static List getAll() { List all = new ArrayList<>(); all.addAll(getConverters()); all.addAll(getCaseChangers()); all.addAll(getOthers()); + all.addAll(getTitleChangers()); return all; } @@ -123,9 +136,21 @@ public static Optional getFormatterForModifier(String modifier) { return Optional.of(new TitleCaseFormatter()); case "sentencecase": return Optional.of(new SentenceCaseFormatter()); + case "veryshorttitle": + return Optional.of(new VeryShortTitleFormatter()); + case "shorttitle": + return Optional.of(new ShortTitleFormatter()); } - if (modifier.startsWith(RegexFormatter.KEY)) { + if (modifier.contains("camel")) { + modifier = modifier.replace("camel", ""); + if (modifier.isEmpty()) { + return Optional.of(new CamelFormatter()); + } else { + int length = Integer.parseInt(modifier); + return Optional.of(new CamelNFormatter(length)); + } + } else if (modifier.startsWith(RegexFormatter.KEY)) { String regex = modifier.substring(RegexFormatter.KEY.length()); return Optional.of(new RegexFormatter(regex)); } else if (TRUNCATE_PATTERN.matcher(modifier).matches()) { diff --git a/src/main/java/org/jabref/logic/formatter/casechanger/CamelFormatter.java b/src/main/java/org/jabref/logic/formatter/casechanger/CamelFormatter.java new file mode 100644 index 00000000000..2d314fc440e --- /dev/null +++ b/src/main/java/org/jabref/logic/formatter/casechanger/CamelFormatter.java @@ -0,0 +1,42 @@ +package org.jabref.logic.formatter.casechanger; + +import java.util.stream.Collectors; + +import org.jabref.logic.cleanup.Formatter; +import org.jabref.logic.l10n.Localization; + +public class CamelFormatter extends Formatter { + + @Override + public String getName() { + return Localization.lang("Camel case"); + } + + @Override + public String getKey() { + return "camel_case"; + } + + @Override + public String format(String input) { + Title title = new Title(input); + + return title.getWords().stream() + .map(Word -> { + Word.toUpperFirst(); + return Word.toString(); + }) + .collect(Collectors.joining("")); + } + + @Override + public String getDescription() { + return Localization.lang( + "Returns capitalized and concatenated title."); + } + + @Override + public String getExampleInput() { + return "this is example input"; + } +} diff --git a/src/main/java/org/jabref/logic/formatter/casechanger/CamelNFormatter.java b/src/main/java/org/jabref/logic/formatter/casechanger/CamelNFormatter.java new file mode 100644 index 00000000000..d3e2efe86ca --- /dev/null +++ b/src/main/java/org/jabref/logic/formatter/casechanger/CamelNFormatter.java @@ -0,0 +1,48 @@ +package org.jabref.logic.formatter.casechanger; + +import java.util.stream.Collectors; + +import org.jabref.logic.cleanup.Formatter; +import org.jabref.logic.l10n.Localization; + +public class CamelNFormatter extends Formatter { + private final int length; + + public CamelNFormatter(int length) { + this.length = length; + } + + @Override + public String getName() { + return Localization.lang("Camel case - n letters max"); + } + + @Override + public String getKey() { + return "camel_case_n"; + } + + @Override + public String format(String input) { + Title title = new Title(input); + + return title.getWords().stream() + .map(Word -> { + Word.toUpperFirst(); + return Word.toString(); + }) + .limit(length) + .collect(Collectors.joining("")); + } + + @Override + public String getDescription() { + return Localization.lang( + "Returns capitalized and concatenated title to N length."); + } + + @Override + public String getExampleInput() { + return "this is camel formatter"; + } +} diff --git a/src/main/java/org/jabref/logic/formatter/casechanger/ShortTitleFormatter.java b/src/main/java/org/jabref/logic/formatter/casechanger/ShortTitleFormatter.java new file mode 100644 index 00000000000..6e9da157286 --- /dev/null +++ b/src/main/java/org/jabref/logic/formatter/casechanger/ShortTitleFormatter.java @@ -0,0 +1,43 @@ +package org.jabref.logic.formatter.casechanger; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.jabref.logic.cleanup.Formatter; +import org.jabref.logic.l10n.Localization; + +public class ShortTitleFormatter extends Formatter { + + @Override + public String getName() { + return Localization.lang("Short title"); + } + + @Override + public String getKey() { + return "short_title"; + } + + @Override + public String format(String input) { + Title title = new Title(input); + + return title.getWords().stream() + .filter(Predicate.not( + Word::isSmallerWord)) + .map(Word::toString) + .limit(3) + .collect(Collectors.joining(" ")); + } + + @Override + public String getDescription() { + return Localization.lang( + "Returns first 3 words of the title ignoring any function words."); + } + + @Override + public String getExampleInput() { + return "This is a short title"; + } +} diff --git a/src/main/java/org/jabref/logic/formatter/casechanger/VeryShortTitleFormatter.java b/src/main/java/org/jabref/logic/formatter/casechanger/VeryShortTitleFormatter.java new file mode 100644 index 00000000000..20332909f13 --- /dev/null +++ b/src/main/java/org/jabref/logic/formatter/casechanger/VeryShortTitleFormatter.java @@ -0,0 +1,43 @@ +package org.jabref.logic.formatter.casechanger; + +import java.util.Optional; +import java.util.function.Predicate; + +import org.jabref.logic.cleanup.Formatter; +import org.jabref.logic.l10n.Localization; + +public class VeryShortTitleFormatter extends Formatter { + + @Override + public String getName() { + return Localization.lang("Very short title"); + } + + @Override + public String getKey() { + return "very_short_title"; + } + + @Override + public String format(String input) { + Title title = new Title(input); + + Optional resultTitle = title.getWords().stream() + .filter(Predicate.not( + Word::isSmallerWord)) + .findFirst(); + + return resultTitle.map(Word::toString).orElse(""); + } + + @Override + public String getDescription() { + return Localization.lang( + "Returns first word of the title ignoring any function words."); + } + + @Override + public String getExampleInput() { + return "A very short title"; + } +} diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ACS.java b/src/main/java/org/jabref/logic/importer/fetcher/ACS.java index 964ad8f38f3..e9f446578b6 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ACS.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ACS.java @@ -1,12 +1,12 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.net.URL; import java.util.Objects; import java.util.Optional; import org.jabref.logic.importer.FulltextFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; @@ -45,7 +45,7 @@ public Optional findFullText(BibEntry entry) throws IOException { if (link != null) { LOGGER.info("Fulltext PDF found @ ACS."); - return Optional.of(URI.create(source.replaceFirst("/abs/", "/pdf/")).toURL()); + return Optional.of(URLUtil.create(source.replaceFirst("/abs/", "/pdf/"))); } return Optional.empty(); } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java index 64ca0c70c1b..527dac0bd16 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java @@ -2,13 +2,13 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.util.Objects; import java.util.Optional; import org.jabref.logic.importer.FulltextFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; @@ -48,7 +48,7 @@ public Optional findFullText(BibEntry entry) throws IOException { if (code == 200) { LOGGER.info("Fulltext PDF found @ APS."); try { - return Optional.of(URI.create(pdfRequestUrl).toURL()); + return Optional.of(URLUtil.create(pdfRequestUrl)); } catch (MalformedURLException e) { LOGGER.warn("APS returned malformed URL, cannot find PDF."); } @@ -77,7 +77,7 @@ private Optional getId(String doi) { URLConnection con; try { - con = URI.create(doiRequest).toURL().openConnection(); + con = URLUtil.create(doiRequest).openConnection(); con.connect(); con.getInputStream(); String[] urlParts = con.getURL().toString().split("abstract/"); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java index e7b72137944..8ab2a590915 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -34,6 +33,7 @@ import org.jabref.logic.importer.PagedSearchBasedFetcher; import org.jabref.logic.importer.fetcher.transformers.ArXivQueryTransformer; import org.jabref.logic.integrity.BracesCorrector; +import org.jabref.logic.util.URLUtil; import org.jabref.logic.util.io.XMLUtil; import org.jabref.logic.util.strings.StringSimilarity; import org.jabref.model.entry.BibEntry; @@ -710,7 +710,7 @@ public ArXivEntry(Node item) { if (linkTitle.equals(Optional.of("pdf"))) { pdfUrlParsed = XMLUtil.getAttributeContent(linkNode, "href").map(url -> { try { - return URI.create(url).toURL(); + return URLUtil.create(url); } catch (MalformedURLException e) { return null; } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java b/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java index 6f057c34480..3661ea22f80 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/BibsonomyScraper.java @@ -1,7 +1,6 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.net.URL; import java.util.Optional; @@ -10,6 +9,7 @@ import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.slf4j.Logger; @@ -37,7 +37,7 @@ public static Optional getEntry(String entryUrl, ImportFormatPreferenc String cleanURL = entryUrl.replace("%", "%25").replace(":", "%3A").replace("/", "%2F").replace("?", "%3F") .replace("&", "%26").replace("=", "%3D"); - URL url = URI.create(BibsonomyScraper.BIBSONOMY_SCRAPER + cleanURL + BibsonomyScraper.BIBSONOMY_SCRAPER_POST).toURL(); + URL url = URLUtil.create(BibsonomyScraper.BIBSONOMY_SCRAPER + cleanURL + BibsonomyScraper.BIBSONOMY_SCRAPER_POST); String bibtex = new URLDownload(url).asString(); return BibtexParser.singleFromString(bibtex, importFormatPreferences); } catch (IOException | FetcherException ex) { diff --git a/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java b/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java index c18794653b7..a7e066cc1f8 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java @@ -1,7 +1,6 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.net.URL; import java.util.List; import java.util.Objects; @@ -15,6 +14,7 @@ import org.jabref.logic.importer.SearchBasedFetcher; import org.jabref.logic.importer.fetcher.transformers.CiteSeerQueryTransformer; import org.jabref.logic.importer.fileformat.CiteSeerParser; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -103,13 +103,13 @@ public Optional findFullText(BibEntry entry) throws IOException, FetcherExc Optional id = entry.getField(StandardField.DOI); if (id.isPresent()) { String source = PDF_URL.formatted(id.get()); - return Optional.of(URI.create(source).toURL()); + return Optional.of(URLUtil.create(source)); } // if using id fails, we can try the source URL Optional urlString = entry.getField(StandardField.URL); if (urlString.isPresent()) { - return Optional.of(URI.create(urlString.get()).toURL()); + return Optional.of(URLUtil.create(urlString.get())); } return Optional.empty(); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java index 19f01d025a0..2aa9305a869 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/DoiFetcher.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.util.Collections; @@ -27,6 +26,7 @@ import org.jabref.logic.importer.util.MediaTypes; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; @@ -122,7 +122,7 @@ public Optional performSearchById(String identifier) throws FetcherExc URL doiURL; try { - doiURL = URI.create(doi.get().getURIAsASCIIString()).toURL(); + doiURL = URLUtil.create(doi.get().getURIAsASCIIString()); } catch (MalformedURLException e) { throw new FetcherException("Malformed URL", e); } @@ -219,7 +219,7 @@ public List performSearch(BibEntry entry) throws FetcherException { public Optional getAgency(DOI doi) throws FetcherException, MalformedURLException { Optional agency = Optional.empty(); try { - URLDownload download = getUrlDownload(URI.create(DOI.AGENCY_RESOLVER + "/" + doi.asString()).toURL()); + URLDownload download = getUrlDownload(URLUtil.create(DOI.AGENCY_RESOLVER + "/" + doi.asString())); JSONObject response = new JSONArray(download.asString()).getJSONObject(0); if (response != null) { agency = Optional.ofNullable(response.optString("RA")); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/DoiResolution.java b/src/main/java/org/jabref/logic/importer/fetcher/DoiResolution.java index 81402a3e499..b66b44ca119 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/DoiResolution.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/DoiResolution.java @@ -18,6 +18,7 @@ import org.jabref.logic.importer.WebFetchers; import org.jabref.logic.net.URLDownload; import org.jabref.logic.preferences.DOIPreferences; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; @@ -61,7 +62,7 @@ public Optional findFullText(BibEntry entry) throws IOException { String doiLink; if (doiPreferences.isUseCustom()) { - base = URI.create(doiPreferences.getDefaultBaseURI()).toURL(); + base = URLUtil.create(doiPreferences.getDefaultBaseURI()); doiLink = doi.get() .getExternalURIWithCustomBase(base.toString()) .map(URI::toASCIIString) @@ -110,11 +111,11 @@ public Optional findFullText(BibEntry entry) throws IOException { // See https://github.com/lehner/LocalCopy for more scrape ideas // link with "PDF" in title tag if (element.attr("title").toLowerCase(Locale.ENGLISH).contains("pdf") && new URLDownload(href).isPdf()) { - return Optional.of(URI.create(href).toURL()); + return Optional.of(URLUtil.create(href)); } if (href.contains("pdf") || hrefText.contains("pdf") && new URLDownload(href).isPdf()) { - links.add(URI.create(href).toURL()); + links.add(URLUtil.create(href)); } } @@ -128,7 +129,7 @@ public Optional findFullText(BibEntry entry) throws IOException { } catch (UnsupportedMimeTypeException type) { // this might be the PDF already as we follow redirects if (type.getMimeType().startsWith("application/pdf")) { - return Optional.of(URI.create(type.getUrl()).toURL()); + return Optional.of(URLUtil.create(type.getUrl())); } LOGGER.warn("DoiResolution fetcher failed: ", type); } catch (IOException e) { @@ -148,7 +149,7 @@ private Optional citationMetaTag(Document html) { if (citationPdfUrl.isPresent()) { try { - return Optional.of(URI.create(citationPdfUrl.get()).toURL()); + return Optional.of(URLUtil.create(citationPdfUrl.get())); } catch (MalformedURLException e) { return Optional.empty(); } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java b/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java index c021916480d..4fbfba362e2 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java @@ -4,7 +4,6 @@ import java.io.StringReader; import java.net.HttpCookie; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -25,6 +24,7 @@ import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.paging.Page; @@ -108,7 +108,7 @@ private Optional search(String url) throws IOException { // TODO: check title inside pdf + length? // TODO: report error function needed?! query -> result LOGGER.info("Fulltext PDF found @ Google: {}", target); - pdfLink = Optional.of(URI.create(target).toURL()); + pdfLink = Optional.of(URLUtil.create(target)); break; } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java index cfbf973162a..2a5e36b3a33 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java @@ -3,7 +3,6 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -24,6 +23,7 @@ import org.jabref.logic.importer.fetcher.transformers.IEEEQueryTransformer; import org.jabref.logic.net.URLDownload; import org.jabref.logic.os.OS; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.StandardField; @@ -202,7 +202,7 @@ public Optional findFullText(BibEntry entry) throws FetcherException { LOGGER.debug("Full text document found on IEEE Xplore"); URL value; try { - value = URI.create(matcher.group(1)).toURL(); + value = URLUtil.create(matcher.group(1)); } catch (MalformedURLException e) { throw new FetcherException("Malformed URL", e); } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java index 65899f49237..7e605166836 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/IacrEprintFetcher.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.util.Objects; import java.util.Optional; @@ -17,6 +16,7 @@ import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.strings.StringUtil; @@ -63,7 +63,7 @@ public Optional performSearchById(String identifier) throws FetcherExc private Optional createEntryFromIacrCitation(String validIdentifier) throws FetcherException { URL url; try { - url = URI.create(CITATION_URL_PREFIX + validIdentifier).toURL(); + url = URLUtil.create(CITATION_URL_PREFIX + validIdentifier); } catch (MalformedURLException e) { throw new FetcherException("Invalid URL", e); } @@ -83,7 +83,7 @@ private Optional createEntryFromIacrCitation(String validIdentifier) t private void setAdditionalFields(BibEntry entry, String identifier) throws FetcherException { URL entryUrl; try { - entryUrl = URI.create(DESCRIPTION_URL_PREFIX + identifier).toURL(); + entryUrl = URLUtil.create(DESCRIPTION_URL_PREFIX + identifier); } catch (MalformedURLException e) { throw new FetcherException("Invalid URL", e); } @@ -96,7 +96,7 @@ private void setAdditionalFields(BibEntry entry, String identifier) throws Fetch // Version information for entries after year 2000 if (isFromOrAfterYear2000(entry)) { try { - entryUrl = URI.create(VERSION_URL_PREFIX + identifier).toURL(); + entryUrl = URLUtil.create(VERSION_URL_PREFIX + identifier); } catch (MalformedURLException e) { throw new FetcherException("Invalid URL", e); } @@ -160,7 +160,7 @@ public Optional findFullText(BibEntry entry) throws IOException, FetcherExc if (urlField.isPresent()) { URL url; try { - url = URI.create(urlField.get()).toURL(); + url = URLUtil.create(urlField.get()); } catch (MalformedURLException e) { LOGGER.warn("Invalid URL {}", urlField.get(), e); return Optional.empty(); @@ -173,7 +173,7 @@ public Optional findFullText(BibEntry entry) throws IOException, FetcherExc // getRequiredValueBetween refuses to match across the line break. fulltextLinkAsInHtml = fulltextLinkAsInHtml.replaceFirst(".*href=\"/", "").trim(); String fulltextLink = FULLTEXT_URL_PREFIX + fulltextLinkAsInHtml + ".pdf"; - return Optional.of(URI.create(fulltextLink).toURL()); + return Optional.of(URLUtil.create(fulltextLink)); } return Optional.empty(); } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java index 3eb00e2acae..dbbe5fa2c24 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -23,6 +22,7 @@ import org.jabref.logic.importer.fetcher.transformers.JstorQueryTransformer; import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -66,10 +66,10 @@ public URL getUrlForIdentifier(String identifier) throws MalformedURLException { if (identifier.contains("/")) { // if identifier links to a entry with a valid doi - return URI.create(start + identifier).toURL(); + return URLUtil.create(start + identifier); } // else use default doi start. - return URI.create(start + "10.2307/" + identifier).toURL(); + return URLUtil.create(start + "10.2307/" + identifier); } @Override @@ -126,7 +126,7 @@ public Optional findFullText(BibEntry entry) throws FetcherException, IOExc } String url = elements.getFirst().attr("href"); - return Optional.of(URI.create(url).toURL()); + return Optional.of(URLUtil.create(url)); } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/Medra.java b/src/main/java/org/jabref/logic/importer/fetcher/Medra.java index 7566f50f4d8..0d1f01a2b6f 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/Medra.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/Medra.java @@ -1,7 +1,6 @@ package org.jabref.logic.importer.fetcher; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; @@ -15,6 +14,7 @@ import org.jabref.logic.importer.util.JsonReader; import org.jabref.logic.importer.util.MediaTypes; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.Author; import org.jabref.model.entry.AuthorList; import org.jabref.model.entry.BibEntry; @@ -104,7 +104,7 @@ public URLDownload getUrlDownload(URL url) { @Override public URL getUrlForIdentifier(String identifier) throws URISyntaxException, MalformedURLException { - return URI.create(API_URL + "/" + identifier).toURL(); + return URLUtil.create(API_URL + "/" + identifier); } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java b/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java index 05d247b6032..8083b22d5a9 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java @@ -2,12 +2,12 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.util.Objects; import java.util.Optional; import org.jabref.logic.importer.FulltextFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; @@ -67,7 +67,7 @@ public Optional findFullText(DOI doi) throws UnirestException { .map(location -> location.optString("url")) .flatMap(url -> { try { - return Optional.of(URI.create(url).toURL()); + return Optional.of(URLUtil.create(url)); } catch (MalformedURLException e) { LOGGER.debug("Could not determine URL to fetch full text from", e); return Optional.empty(); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java b/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java index 1691bff0ebe..dff0b43a0fb 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ResearchGate.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -24,6 +23,7 @@ import org.jabref.logic.layout.format.RTFChars; import org.jabref.logic.net.URLDownload; import org.jabref.logic.os.OS; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; @@ -77,7 +77,7 @@ public Optional findFullText(BibEntry entry) throws IOException, FetcherExc LOGGER.debug("PDF link: {}", link); if (link.contains("researchgate.net")) { - return Optional.of(URI.create(link).toURL()); + return Optional.of(URLUtil.create(link)); } return Optional.empty(); } @@ -254,7 +254,7 @@ public List performSearch(QueryNode luceneQuery) throws FetcherExcepti private BufferedReader getInputStream(String urlString) { try { - URL url = URI.create(urlString).toURL(); + URL url = URLUtil.create(urlString); return new BufferedReader(new InputStreamReader(url.openStream())); } catch (IOException e) { LOGGER.debug("Wrong URL", e); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java b/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java index f2559d2f0ec..43fba83c175 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.util.Objects; import java.util.Optional; @@ -11,6 +10,7 @@ import org.jabref.logic.importer.FulltextFetcher; import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; @@ -71,7 +71,7 @@ public Optional findFullText(BibEntry entry) throws IOException { Elements metaLinks = html.getElementsByAttributeValue("name", "citation_pdf_url"); if (!metaLinks.isEmpty()) { String link = metaLinks.first().attr("content"); - return Optional.of(URI.create(link).toURL()); + return Optional.of(URLUtil.create(link)); } // We use the ScienceDirect web page which contains the article (presented using HTML). @@ -102,7 +102,7 @@ public Optional findFullText(BibEntry entry) throws IOException { String fullLinkToPdf; if (pdfDownload.has("linkToPdf")) { String linkToPdf = pdfDownload.getString("linkToPdf"); - URL url = URI.create(urlFromDoi).toURL(); + URL url = URLUtil.create(urlFromDoi); fullLinkToPdf = "%s://%s%s".formatted(url.getProtocol(), url.getAuthority(), linkToPdf); } else if (pdfDownload.has("urlMetadata")) { JSONObject urlMetadata = pdfDownload.getJSONObject("urlMetadata"); @@ -122,7 +122,7 @@ public Optional findFullText(BibEntry entry) throws IOException { LOGGER.info("Fulltext PDF found at ScienceDirect at {}.", fullLinkToPdf); try { - return Optional.of(URI.create(fullLinkToPdf).toURL()); + return Optional.of(URLUtil.create(fullLinkToPdf)); } catch (MalformedURLException e) { LOGGER.error("malformed URL", e); return Optional.empty(); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java b/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java index 45aa343a333..c46772da100 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/SemanticScholar.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -23,6 +22,7 @@ import org.jabref.logic.importer.fetcher.transformers.DefaultQueryTransformer; import org.jabref.logic.importer.util.JsonReader; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.ArXivIdentifier; @@ -115,7 +115,7 @@ public Optional findFullText(BibEntry entry) throws IOException, FetcherExc return Optional.empty(); } LOGGER.info("Fulltext PDF found @ SemanticScholar. Link: {}", link); - return Optional.of(URI.create(link).toURL()); + return Optional.of(URLUtil.create(link)); } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java index aa21089d253..71cce64e126 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java @@ -3,7 +3,6 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -17,6 +16,7 @@ import org.jabref.logic.importer.Parser; import org.jabref.logic.importer.fetcher.transformers.SpringerQueryTransformer; import org.jabref.logic.os.OS; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.Month; @@ -130,7 +130,7 @@ public static BibEntry parseSpringerJSONtoBibtex(JSONObject springerJsonEntry) { JSONObject url = (JSONObject) data; if ("pdf".equalsIgnoreCase(url.optString("format"))) { try { - entry.addFile(new LinkedFile(URI.create(url.optString("value")).toURL(), "PDF")); + entry.addFile(new LinkedFile(URLUtil.create(url.optString("value")), "PDF")); } catch (MalformedURLException e) { LOGGER.info("Malformed URL: {}", url.optString("value")); } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java b/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java index 1e918099990..ed4ccda242b 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; -import java.net.URI; import java.time.DateTimeException; import java.util.Arrays; import java.util.LinkedList; @@ -19,6 +18,7 @@ import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.Parser; import org.jabref.logic.util.StandardFileType; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.AuthorList; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.Date; @@ -401,7 +401,7 @@ private void putElectronicLocation(BibEntry bibEntry, Element datafield) { private static void handleVolltext(BibEntry bibEntry, String fieldName, String resource, Field fallBackField) { if ("Volltext".equals(fieldName) && StringUtil.isNotBlank(resource)) { try { - LinkedFile linkedFile = new LinkedFile("", URI.create(resource).toURL(), StandardFileType.PDF.getName()); + LinkedFile linkedFile = new LinkedFile("", URLUtil.create(resource), StandardFileType.PDF.getName()); bibEntry.setFiles(List.of(linkedFile)); } catch (MalformedURLException | IllegalArgumentException e) { LOGGER.info("Malformed URL: {}", resource); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java index ca266e8c895..7d43be038a4 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java @@ -218,7 +218,7 @@ public ParserResult importDatabase(Path filePath) { private static String extractTitleFromDocument(PDDocument document) throws IOException { TitleExtractorByFontSize stripper = new TitleExtractorByFontSize(); - return stripper.getTitleFromFirstPage(document); + return stripper.getTitle(document); } private static class TitleExtractorByFontSize extends PDFTextStripper { @@ -230,9 +230,9 @@ public TitleExtractorByFontSize() { this.textPositionsList = new ArrayList<>(); } - public String getTitleFromFirstPage(PDDocument document) throws IOException { + public String getTitle(PDDocument document) throws IOException { this.setStartPage(1); - this.setEndPage(1); + this.setEndPage(2); this.writeText(document, new StringWriter()); return findLargestFontText(textPositionsList); } diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 695c0a48cbe..59527031e4c 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -1,12 +1,12 @@ package org.jabref.logic.importer.util; import java.net.MalformedURLException; -import java.net.URI; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.LinkedFile; import org.slf4j.Logger; @@ -59,7 +59,7 @@ public List parse() { if (LinkedFile.isOnlineLink(value.trim())) { // needs to be modifiable try { - return List.of(new LinkedFile(URI.create(value).toURL(), "")); + return List.of(new LinkedFile(URLUtil.create(value), "")); } catch (MalformedURLException e) { LOGGER.error("invalid url", e); return files; @@ -157,7 +157,7 @@ static LinkedFile convert(List entry) { LinkedFile field = null; if (LinkedFile.isOnlineLink(entry.get(1))) { try { - field = new LinkedFile(entry.getFirst(), URI.create(entry.get(1)).toURL(), entry.get(2)); + field = new LinkedFile(entry.getFirst(), URLUtil.create(entry.get(1)), entry.get(2)); } catch (MalformedURLException e) { // in case the URL is malformed, store it nevertheless field = new LinkedFile(entry.getFirst(), entry.get(1), entry.get(2)); diff --git a/src/main/java/org/jabref/logic/layout/format/DOICheck.java b/src/main/java/org/jabref/logic/layout/format/DOICheck.java index ed9f2a6fd7b..6f0606291e4 100644 --- a/src/main/java/org/jabref/logic/layout/format/DOICheck.java +++ b/src/main/java/org/jabref/logic/layout/format/DOICheck.java @@ -4,6 +4,7 @@ import org.jabref.logic.layout.LayoutFormatter; import org.jabref.logic.preferences.DOIPreferences; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.identifier.DOI; /** @@ -31,7 +32,7 @@ public String format(String fieldText) { } if (doiPreferences.isUseCustom()) { - var base = URI.create(doiPreferences.getDefaultBaseURI()); + var base = URLUtil.createUri(doiPreferences.getDefaultBaseURI()); return DOI.parse(result).flatMap(doi -> doi.getExternalURIFromBase(base)) .map(URI::toASCIIString) .orElse(result); diff --git a/src/main/java/org/jabref/logic/net/URLDownload.java b/src/main/java/org/jabref/logic/net/URLDownload.java index 6fb9db4cabe..32993af4eff 100644 --- a/src/main/java/org/jabref/logic/net/URLDownload.java +++ b/src/main/java/org/jabref/logic/net/URLDownload.java @@ -15,7 +15,6 @@ import java.net.HttpCookie; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; @@ -42,6 +41,7 @@ import org.jabref.logic.importer.FetcherClientException; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.FetcherServerException; +import org.jabref.logic.util.URLUtil; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.strings.StringUtil; @@ -90,7 +90,7 @@ public class URLDownload { * @throws MalformedURLException if no protocol is specified in the source, or an unknown protocol is found */ public URLDownload(String source) throws MalformedURLException { - this(URI.create(source).toURL()); + this(URLUtil.create(source)); } /** @@ -153,7 +153,7 @@ public Optional getMimeType() { // Try to resolve local URIs try { - URLConnection connection = URI.create(source.toString()).toURL().openConnection(); + URLConnection connection = URLUtil.create(source.toString()).openConnection(); contentType = connection.getContentType(); if (!StringUtil.isNullOrEmpty(contentType)) { return Optional.of(contentType); diff --git a/src/main/java/org/jabref/logic/openoffice/action/Update.java b/src/main/java/org/jabref/logic/openoffice/action/Update.java index 7294842e732..8c31ee37e68 100644 --- a/src/main/java/org/jabref/logic/openoffice/action/Update.java +++ b/src/main/java/org/jabref/logic/openoffice/action/Update.java @@ -64,8 +64,7 @@ private static List updateDocument(XTextDocument doc, } return frontend.citationGroups.getUnresolvedKeys(); - } catch ( - IOException e) { + } catch (IOException e) { Logger.warn("Error while updating document", e); } finally { if (useLockControllers && UnoScreenRefresh.hasControllersLocked(doc)) { diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java index 865806947f3..e9c611f02ec 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java @@ -69,7 +69,6 @@ public void insertCitation(XTextCursor cursor, CitationStyle selectedStyle, List OOText ooText = OOFormat.setLocaleNone(OOText.fromString(formattedCitation)); insertReferences(cursor, entries, ooText, selectedStyle.isNumericStyle()); - cursor.collapseToEnd(); } /** @@ -119,7 +118,6 @@ public void insertInTextCitation(XTextCursor cursor, CitationStyle selectedStyle } OOText ooText = OOFormat.setLocaleNone(OOText.fromString(finalText)); insertReferences(cursor, List.of(currentEntry), ooText, selectedStyle.isNumericStyle()); - cursor.collapseToEnd(); } } @@ -131,9 +129,6 @@ public void insertEmpty(XTextCursor cursor, CitationStyle selectedStyle, List entries, OOText CSLReferenceMark mark = markManager.createReferenceMark(entries); mark.insertReferenceIntoOO(document, cursor, ooText, !preceedingSpaceExists, false); - // Move the cursor to the end of the inserted text - cursor.collapseToEnd(); - markManager.setUpdateRequired(isNumericStyle); readAndUpdateExistingMarks(); - cursor.collapseToEnd(); } /** diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java index 1ac64172287..525a1803be5 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java @@ -72,6 +72,15 @@ public static String transformHTML(String html) { // Clean up any remaining span tags html = html.replaceAll("]*>", ""); + // Convert line breaks to paragraph breaks + html = html.replaceAll("[\n\r]+", "

"); + + // Remove leading paragraph tags (preserving any whitespaces after them for indentation) + html = html.replaceAll("^\\s*

\\s*

", ""); + + // Remove extra trailing paragraph tags when there are multiple (keeping one) + html = html.replaceAll("(?:

\\s*

\\s*){2,}$", "

"); + return html; } @@ -113,9 +122,9 @@ public static String generateAlphanumericCitation(List entries, BibDat /** * Method to update citation number of a bibliographic entry (to be inserted in the list of references). - * By default, citeproc-java ({@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateBibliography(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateBibliography} always start the numbering of a list of citations with "1". - * If a citation doesn't correspond to the first cited entry, the number should be changed to the relevant current citation number. - * If an entries has been cited before, the colder number should be reused. + * By default, citeproc-java ({@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateBibliography(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateBibliography} always starts the numbering of a list of citations with "1". + * If a citation doesn't correspond to the first cited entry, the number should be changed to the appropriate current citation number. + * The numbers should be globally unique. If an entry has been cited before, the older citation number corresponding to it should be reused. * The number can be enclosed in different formats, such as "1", "1.", "1)", "(1)" or "[1]". *

* Precondition: Use ONLY with numeric citation styles.

diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java index 107974934b4..732db3899ec 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java @@ -101,9 +101,7 @@ private void populateCSLBibTextSection(XTextDocument doc, // Use CSLCitationOOAdapter to insert the bibliography cslAdapter.insertBibliography(cursor, citationStyle, entries, bibDatabaseContext, bibEntryTypesManager); - LOGGER.debug("Bibliography inserted using CSLCitationOOAdapter"); - cursor.collapseToEnd(); LOGGER.debug("CSL bibliography section population completed"); } } diff --git a/src/main/java/org/jabref/logic/os/OS.java b/src/main/java/org/jabref/logic/os/OS.java index 3bba6e3ee33..df2f942aad8 100644 --- a/src/main/java/org/jabref/logic/os/OS.java +++ b/src/main/java/org/jabref/logic/os/OS.java @@ -49,8 +49,7 @@ public static String getHostName() { if (StringUtil.isBlank(hostName)) { try { hostName = InetAddress.getLocalHost().getHostName(); - } catch ( - UnknownHostException e) { + } catch (UnknownHostException e) { LoggerFactory.getLogger(OS.class).info("Hostname not found. Using \"localhost\" as fallback.", e); hostName = "localhost"; } @@ -65,12 +64,10 @@ public static boolean isKeyringAvailable() { return false; } keyring.deletePassword("JabRef", "keyringTest"); - } catch ( - BackendNotSupportedException ex) { + } catch (BackendNotSupportedException ex) { LoggerFactory.getLogger(OS.class).warn("Credential store not supported."); return false; - } catch ( - PasswordAccessException ex) { + } catch (PasswordAccessException ex) { LoggerFactory.getLogger(OS.class).warn("Password storage in credential store failed."); return false; } catch (Exception ex) { @@ -90,9 +87,8 @@ public static String detectProgramPath(String programName, String directoryName) try { ShellLink link = new ShellLink(texworksLinkPath); return link.resolveTarget(); - } catch ( - IOException | - ShellLinkException e) { + } catch (IOException + | ShellLinkException e) { // Static logger instance cannot be used. See the class comment. Logger logger = Logger.getLogger(OS.class.getName()); logger.log(Level.WARNING, "Had an error while reading .lnk file for TeXworks", e); diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java new file mode 100644 index 00000000000..fd6317d9d23 --- /dev/null +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -0,0 +1,115 @@ +package org.jabref.logic.util; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +/** + * URL utilities for URLs in the JabRef logic. + *

+ * For GUI-oriented URL utilities see {@link org.jabref.gui.fieldeditors.URLUtil}. + */ +public class URLUtil { + private static final String URL_EXP = "^(https?|ftp)://.+"; + // Detect Google search URL + private static final String GOOGLE_SEARCH_EXP = "^https?://(?:www\\.)?google\\.[\\.a-z]+?/url.*"; + + /** + * Cleans URLs returned by Google search. + * + * If you copy links from search results from Google, all links will be enriched with search meta data, e.g. + * https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&&url=http%3A%2F%2Fwww.inrg.csie.ntu.edu.tw%2Falgorithm2014%2Fhomework%2FWagner-74.pdf&ei=DifeVYHkDYWqU5W0j6gD&usg=AFQjCNFl638rl5KVta1jIMWLyb4CPSZidg&sig2=0hSSMw9XZXL3HJWwEcJtOg + * + * + * @param url the Google search URL string + * @return the cleaned Google URL or @code{url} if no search URL was detected + */ + public static String cleanGoogleSearchURL(String url) { + Objects.requireNonNull(url); + + if (!url.matches(GOOGLE_SEARCH_EXP)) { + return url; + } + // Extract destination URL + try { + URL searchURL = create(url); + // URL parameters + String query = searchURL.getQuery(); + // no parameters + if (query == null) { + return url; + } + // extract url parameter + String[] pairs = query.split("&"); + + for (String pair : pairs) { + // "clean" url is decoded value of "url" parameter + if (pair.startsWith("url=")) { + String value = pair.substring(pair.indexOf('=') + 1); + + String decode = URLDecoder.decode(value, StandardCharsets.UTF_8); + // url? + if (decode.matches(URL_EXP)) { + return decode; + } + } + } + return url; + } catch (MalformedURLException e) { + return url; + } + } + + /** + * Checks whether the given String is a URL. + *

+ * Currently only checks for a protocol String. + * + * @param url the String to check for a URL + * @return true if url contains a valid URL + */ + public static boolean isURL(String url) { + try { + create(url); + return true; + } catch (MalformedURLException | IllegalArgumentException e) { + return false; + } + } + + /** + * Creates a {@link URL} object from the given string URL. + * + * @param url the URL string to be converted into a {@link URL}. + * @return the {@link URL} object created from the string URL. + * @throws MalformedURLException if the URL is malformed and cannot be converted to a {@link URL}. + */ + public static URL create(String url) throws MalformedURLException { + return createUri(url).toURL(); + } + + /** + * Creates a {@link URI} object from the given string URL. + * This method attempts to convert the given URL string into a {@link URI} object. + * The pipe character ('|') is replaced with its percent-encoded equivalent ("%7C") because the pipe character + * is only a valid character according to RFC3986. However, JDK's URI implementation is implementing RFC2396 and RFC2732, but not RFC3986. + * + * @param url the URL string to be converted into a {@link URI}. + * @return the {@link URI} object created from the string URL. + * @throws IllegalArgumentException if the string URL is not a valid URI or if the URI format is incorrect. + * @throws URISyntaxException if the string URL has an invalid syntax and cannot be converted into a {@link URI}. + */ + public static URI createUri(String url) { + try { + // Replace '|' character with its percent-encoded representation '%7C'. + String urlFormat = url.replace("|", "%7C"); + return new URI(urlFormat); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/src/main/java/org/jabref/logic/util/Version.java b/src/main/java/org/jabref/logic/util/Version.java index 5e10be4390b..1380c90e109 100644 --- a/src/main/java/org/jabref/logic/util/Version.java +++ b/src/main/java/org/jabref/logic/util/Version.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; -import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -106,7 +105,7 @@ public static Version parse(String version) { * Grabs all the available releases from the GitHub repository */ public static List getAllAvailableVersions() throws IOException { - HttpURLConnection connection = (HttpURLConnection) URI.create(JABREF_GITHUB_RELEASES).toURL().openConnection(); + HttpURLConnection connection = (HttpURLConnection) URLUtil.create(JABREF_GITHUB_RELEASES).openConnection(); connection.setRequestProperty("Accept-Charset", "UTF-8"); try (BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { JSONArray objects = new JSONArray(rd.readLine()); diff --git a/src/main/java/org/jabref/logic/util/io/FileUtil.java b/src/main/java/org/jabref/logic/util/io/FileUtil.java index 3240e64034f..5ddb734d8ce 100644 --- a/src/main/java/org/jabref/logic/util/io/FileUtil.java +++ b/src/main/java/org/jabref/logic/util/io/FileUtil.java @@ -576,13 +576,10 @@ public static String shortenFileName(String fileName, Integer maxLength) { numCharsBeforeEllipsis = Math.min(numCharsBeforeEllipsis, name.length()); numCharsAfterEllipsis = Math.min(numCharsAfterEllipsis, name.length() - numCharsBeforeEllipsis); - StringBuilder result = new StringBuilder(); - result.append(name, 0, numCharsBeforeEllipsis) - .append(ELLIPSIS) - .append(name.substring(name.length() - numCharsAfterEllipsis)) - .append(extension); - - return result.toString(); + return name.substring(0, numCharsBeforeEllipsis) + + ELLIPSIS + + name.substring(name.length() - numCharsAfterEllipsis) + + extension; } public static boolean isCharLegal(char c) { diff --git a/src/main/java/org/jabref/model/database/BibDatabaseContext.java b/src/main/java/org/jabref/model/database/BibDatabaseContext.java index bf4aa5154d8..f90a7c64fbd 100644 --- a/src/main/java/org/jabref/model/database/BibDatabaseContext.java +++ b/src/main/java/org/jabref/model/database/BibDatabaseContext.java @@ -162,10 +162,10 @@ public List getFileDirectories(FilePreferences preferences) { // Paths are a) ordered and b) should be contained only once in the result LinkedHashSet fileDirs = new LinkedHashSet<>(3); - Optional userFileDirectory = metaData.getUserFileDirectory(preferences.getUserAndHost()).map(dir -> getFileDirectoryPath(dir)); + Optional userFileDirectory = metaData.getUserFileDirectory(preferences.getUserAndHost()).map(this::getFileDirectoryPath); userFileDirectory.ifPresent(fileDirs::add); - Optional librarySpecificFileDirectory = metaData.getLibrarySpecificFileDirectory().map(dir -> getFileDirectoryPath(dir)); + Optional librarySpecificFileDirectory = metaData.getLibrarySpecificFileDirectory().map(this::getFileDirectoryPath); librarySpecificFileDirectory.ifPresent(fileDirs::add); // fileDirs.isEmpty() is true after these two if there are no directories set in the BIB file itself: diff --git a/src/main/java/org/jabref/model/entry/identifier/ARK.java b/src/main/java/org/jabref/model/entry/identifier/ARK.java index 709b9eb1f7c..0ab41741fd1 100644 --- a/src/main/java/org/jabref/model/entry/identifier/ARK.java +++ b/src/main/java/org/jabref/model/entry/identifier/ARK.java @@ -3,6 +3,9 @@ import java.net.URI; import java.util.Optional; +import org.jabref.architecture.AllowedToUseLogic; +import org.jabref.logic.util.URLUtil; + /** * Archival Resource Key (ARK) identifiers are URLs that support long-term access to information. They are similar to DOIs * only that we don't know of any service that can extract bibliography information from ARKs. For this reason, if an ARK @@ -15,6 +18,7 @@ * and to provide them with ability to copy/paste the ark as is, we support arks with or without the prefix. *

*/ +@AllowedToUseLogic("Because URL utility is needed") public class ARK extends EprintIdentifier { private final String ark; @@ -35,6 +39,6 @@ public String asString() { @Override public Optional getExternalURI() { - return Optional.of(URI.create("https://n2t.net/ark:/" + asString())); + return Optional.of(URLUtil.createUri("https://n2t.net/ark:/" + asString())); } } diff --git a/src/main/java/org/jabref/model/entry/identifier/DOI.java b/src/main/java/org/jabref/model/entry/identifier/DOI.java index 58e5c59c03b..0b05104f50d 100644 --- a/src/main/java/org/jabref/model/entry/identifier/DOI.java +++ b/src/main/java/org/jabref/model/entry/identifier/DOI.java @@ -12,6 +12,7 @@ import org.jabref.architecture.AllowedToUseLogic; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; @@ -24,8 +25,8 @@ @AllowedToUseLogic("because we want to have this class 'smart' an be able to parse obscure DOIs, too. For this, we need the LatexToUnicodeformatter.") public class DOI implements Identifier { - public static final URI AGENCY_RESOLVER = URI.create("https://doi.org/doiRA"); - public static final URI RESOLVER = URI.create("https://doi.org/"); + public static final URI AGENCY_RESOLVER = URLUtil.createUri("https://doi.org/doiRA"); + public static final URI RESOLVER = URLUtil.createUri("https://doi.org/"); private static final Logger LOGGER = LoggerFactory.getLogger(DOI.class); @@ -261,7 +262,7 @@ public Optional getExternalURI() { } public Optional getExternalURIWithCustomBase(String customBase) { - return getExternalURIFromBase(URI.create(customBase)); + return getExternalURIFromBase(URLUtil.createUri(customBase)); } public Optional getExternalURIFromBase(URI base) { diff --git a/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java b/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java index 77a88371d9b..953ef33a35b 100644 --- a/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java +++ b/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java @@ -7,14 +7,17 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.jabref.architecture.AllowedToUseLogic; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@AllowedToUseLogic("Because URL utility is needed") public class IacrEprint implements Identifier { - public static final URI RESOLVER = URI.create("https://ia.cr"); + public static final URI RESOLVER = URLUtil.createUri("https://ia.cr"); private static final Logger LOGGER = LoggerFactory.getLogger(IacrEprint.class); private static final String IACR_EPRINT_EXP = "\\d{4}\\/\\d{3,5}"; diff --git a/src/main/java/org/jabref/model/entry/identifier/SSRN.java b/src/main/java/org/jabref/model/entry/identifier/SSRN.java index fad2eeae069..0a644b6dba1 100644 --- a/src/main/java/org/jabref/model/entry/identifier/SSRN.java +++ b/src/main/java/org/jabref/model/entry/identifier/SSRN.java @@ -6,9 +6,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.jabref.architecture.AllowedToUseLogic; +import org.jabref.logic.util.URLUtil; + /** * Represents an SSRN article, identified by its abstract ID. */ +@AllowedToUseLogic("Because URL utility is needed") public class SSRN extends EprintIdentifier { private static final String SSRN_URL_REGEX = "(https?://)?(papers\\.)?ssrn\\.com/(sol3/papers.cfm\\?)?abstract(_id)?=(?\\d+)"; @@ -63,7 +67,7 @@ public String asString() { @Override public Optional getExternalURI() { - URI uri = URI.create("https://ssrn.com/abstract=" + abstractId); + URI uri = URLUtil.createUri("https://ssrn.com/abstract=" + abstractId); return Optional.of(uri); } diff --git a/src/main/resources/csl-locales b/src/main/resources/csl-locales index 4753e3a9aca..96d704de2fc 160000 --- a/src/main/resources/csl-locales +++ b/src/main/resources/csl-locales @@ -1 +1 @@ -Subproject commit 4753e3a9aca4b806ac0e3036ed727d47bf8f678e +Subproject commit 96d704de2fc7b930ae4a0ec4686a7143bb4a0d33 diff --git a/src/main/resources/csl-styles b/src/main/resources/csl-styles index 568b63625d7..b90b81a58b1 160000 --- a/src/main/resources/csl-styles +++ b/src/main/resources/csl-styles @@ -1 +1 @@ -Subproject commit 568b63625d72c25297b498cf3f658e5691655a41 +Subproject commit b90b81a58b1a260423608f3868a6613cc6efe431 diff --git a/src/main/resources/l10n/JabRef_ar.properties b/src/main/resources/l10n/JabRef_ar.properties index 111db309d93..67e4d9beb81 100644 --- a/src/main/resources/l10n/JabRef_ar.properties +++ b/src/main/resources/l10n/JabRef_ar.properties @@ -232,6 +232,7 @@ Field\ name=اسم الحقل + Import\ preferences=استيراد الإعدادات @@ -468,6 +469,7 @@ Optional\ fields\ 2=الحقول الاختيارية 2 + Could\ not\ run\ the\ 'vim'\ program.=لا يمكن تشغيل برنامَج 'vim'. diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index c06c35711b1..b924730a4ec 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -290,6 +290,7 @@ Highlight=Fremhæv HTML\ table=HTML-tabel HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML-tabell (med Abstract & BibTeX) + Icon=Ikon Ignore=Ignorer @@ -678,6 +679,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Forventet syntaks User-specific\ file\ directory=Brugerspecifikt filbibliotek + Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Autofuldfør kun navne i formatet 'Fornavn Efternavn' Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Autofuldfør kun navne i formatet 'Efternavn, Fornavn' Autocomplete\ names\ in\ both\ formats=Autofuldfør navne i begge formater diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 6c35cb304a1..8041c1a4c80 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -103,7 +103,7 @@ Available\ import\ formats=Verfügbare Importformate Show\ BibTeX\ source=BibTeX-Quellcode anzeigen Show/edit\ %0\ source=%0-Quelltext anzeigen/editieren -Background\ tasks=Hintergrund Job +Background\ tasks=Hintergrundprozesse Background\ tasks\ are\ running=Hintergrundprozesse laufen @@ -466,6 +466,8 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=Der markierte Bereic HTML\ table=HTML-Tabelle HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML-Tabelle (mit Abstract & BibTeX) +Markdown\ titles=Titel im Markdown-Format + Icon=Icon Ignore=Ignorieren @@ -1059,6 +1061,8 @@ Expected\ syntax\ for\ --fetch\='\:'=Erwartete Syntax Library-specific\ file\ directory=Bibliothekseigener Dateipfad User-specific\ file\ directory=Benutzerdefiniertes Dateiverzeichnis LaTeX\ file\ directory=LaTeX-Dateiverzeichnis +Path\ %0\ could\ not\ be\ resolved.\ Using\ working\ dir.=Pfad %0 konnte nicht gefunden werden. Verwende Arbeitsverzeichnis. + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=Sie müssen einen Zahlwert zwischen 1025 und 65535 eintragen Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Automatische Vervollständigung von Namen nur im Format 'Vorname Nachname' @@ -1485,6 +1489,14 @@ HTML\ to\ LaTeX=HTML zu LaTeX LaTeX\ cleanup=LaTeX Aufräumen LaTeX\ to\ Unicode=LaTeX zu Unicode lower\ case=kleinschreibung +Camel\ case=CamelCase +Camel\ case\ -\ n\ letters\ max= CamelCase - max. n Buchstaben +Very\ short\ title=Sehr kurzer Titel +Short\ title=Kurzer Titel +Returns\ first\ word\ of\ the\ title\ ignoring\ any\ function\ words.=Liefert als Ausgabe das erste Wort des Titels, wobei alle Funktionswörter ignoriert werden. +Returns\ first\ 3\ words\ of\ the\ title\ ignoring\ any\ function\ words.=Liefert als Ausgabe die ersten 3 Wörter des Titels, wobei alle Funktionswörter ignoriert werden. +Returns\ capitalized\ and\ concatenated\ title\ to\ N\ length.=Liefert als Ausgabe den großgeschriebenen und verketteten Titel, gekürzt auf Länge N. +Returns\ capitalized\ and\ concatenated\ title.=Liefert als Ausgabe den großgeschriebenen und verketteten Titel. Minify\ list\ of\ person\ names=Reduziere Liste der Personen Normalize\ date=Normalisiere Datum Normalize\ en\ dashes=Gedankenstriche normalisieren diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index 8e758879050..a09b8d2943a 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -378,6 +378,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=Η μαρκαρισ HTML\ table=Πίνακας HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Πίνακας HTML (με Περίληψη & BibTeX) + Icon=Εικονίδιο Ignore=Παράβλεψη @@ -897,6 +898,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Αναμενόμ User-specific\ file\ directory=Φάκελος αρχείου καθορισμένος από τον χρήστη LaTeX\ file\ directory=Κατάλογος αρχείου LaTeX + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=Πρέπει να εισάγετε μια ακέραια τιμή στο διάστημα 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Αυτόματη συμπλήρωση ονομάτων μόνο με τη μορφή 'Όνομα Επώνυμο' Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Αυτόματη συμπλήρωση ονομάτων μόνο με τη μορφή 'Επώνυμο, Όνομα' diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 2a4ab3bef81..f0842f5bab4 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -466,6 +466,8 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text!=The marked area does HTML\ table=HTML table HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML table (with Abstract & BibTeX) +Markdown\ titles=Markdown titles + Icon=Icon Ignore=Ignore @@ -1059,6 +1061,8 @@ Expected\ syntax\ for\ --fetch\='\:'=Expected syntax f Library-specific\ file\ directory=Library-specific file directory User-specific\ file\ directory=User-specific file directory LaTeX\ file\ directory=LaTeX file directory +Path\ %0\ could\ not\ be\ resolved.\ Using\ working\ dir.=Path %0 could not be resolved. Using working dir. + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=You must enter an integer value in the interval 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Autocomplete names in 'Firstname Lastname' format only @@ -1485,6 +1489,14 @@ HTML\ to\ LaTeX=HTML to LaTeX LaTeX\ cleanup=LaTeX cleanup LaTeX\ to\ Unicode=LaTeX to Unicode lower\ case=lower case +Camel\ case=Camel case +Camel\ case\ -\ n\ letters\ max= Camel case - n letters max +Very\ short\ title=Very short title +Short\ title=Short title +Returns\ first\ word\ of\ the\ title\ ignoring\ any\ function\ words.=Returns first word of the title ignoring any function words. +Returns\ first\ 3\ words\ of\ the\ title\ ignoring\ any\ function\ words.=Returns first 3 words of the title ignoring any function words. +Returns\ capitalized\ and\ concatenated\ title\ to\ N\ length.=Returns capitalized and concatenated title to N length. +Returns\ capitalized\ and\ concatenated\ title.=Returns capitalized and concatenated title. Minify\ list\ of\ person\ names=Minify list of person names Normalize\ date=Normalize date Normalize\ en\ dashes=Normalize en dashes diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 3b7fbba315a..5b24695ceb0 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -412,6 +412,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=¡El área marcada n HTML\ table=Tabla HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Tabla HTML (con Abstract BibTeX) + Icon=Icono Ignore=Ignorar @@ -963,6 +964,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Sintaxis esperada User-specific\ file\ directory=Carpeta de archivos de usuario LaTeX\ file\ directory=Directorio de archivos de LaTeX + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=Debe introducir un valor entero en el intervalo 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Autocompletar nombres sólo en el formato 'Nombre Apellidos' Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Autocompletar nombres sólo en el formato 'Apellidos, Nombre' diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index cfec353d983..d6614f7ea65 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -254,6 +254,7 @@ Will\ write\ metadata\ to\ the\ PDFs\ linked\ from\ selected\ entries.=فراد + Open\ file=بازکردن پرونده @@ -419,6 +420,7 @@ Check\ integrity=بررسی بی‌نقصی + Cleanup\ entries=تمیز کردن ورودی‌ها diff --git a/src/main/resources/l10n/JabRef_fi.properties b/src/main/resources/l10n/JabRef_fi.properties index d79921567de..9459fb77f89 100644 --- a/src/main/resources/l10n/JabRef_fi.properties +++ b/src/main/resources/l10n/JabRef_fi.properties @@ -447,6 +447,8 @@ About\ JabRef=Tietoja JabRef + + diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 44205cf0320..5aa3e510fd9 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -466,6 +466,8 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=La zone marquée ne HTML\ table=Tableau HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Tableau HTML (avec Résumé & BibTeX) +Markdown\ titles=Titres Markdown + Icon=Icône Ignore=Ignorer @@ -1059,6 +1061,8 @@ Expected\ syntax\ for\ --fetch\='\:'=Syntaxe attendue Library-specific\ file\ directory=Répertoire spécifique au fichier User-specific\ file\ directory=Répertoire de fichiers spécifique à l'utilisateur LaTeX\ file\ directory=Répertoire de fichiers LaTeX +Path\ %0\ could\ not\ be\ resolved.\ Using\ working\ dir.=Le chemin %0 n'a pas pu être trouvé. Utilisation du répertoire de travail. + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=Vous devez saisir une valeur entière dans l'intervalle 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Complétion automatique des noms uniquement dans le format 'Prénom Nom' @@ -1485,6 +1489,14 @@ HTML\ to\ LaTeX=HTML vers LaTeX LaTeX\ cleanup=Nettoyage LaTeX LaTeX\ to\ Unicode=LaTeX vers Unicode lower\ case=minuscules +Camel\ case=Casse chameau +Camel\ case\ -\ n\ letters\ max= Casse chameau - n lettres max +Very\ short\ title=Titre très court +Short\ title=Titre court +Returns\ first\ word\ of\ the\ title\ ignoring\ any\ function\ words.=Renvoie le premier mot du titre en ignorant tous les mots de liaison. +Returns\ first\ 3\ words\ of\ the\ title\ ignoring\ any\ function\ words.=Renvoie les 3 premiers mots du titre en ignorant tous les mots de liaison. +Returns\ capitalized\ and\ concatenated\ title\ to\ N\ length.=Renvoie le titre en majuscule et concaténé à la longueur N. +Returns\ capitalized\ and\ concatenated\ title.=Retourne le titre en majuscule et concaténé. Minify\ list\ of\ person\ names=Raccourcir la liste des noms de personne Normalize\ date=Harmoniser la date Normalize\ en\ dashes=Harmoniser les tirets cadratins diff --git a/src/main/resources/l10n/JabRef_id.properties b/src/main/resources/l10n/JabRef_id.properties index 3808f0f5c8e..6993281a9da 100644 --- a/src/main/resources/l10n/JabRef_id.properties +++ b/src/main/resources/l10n/JabRef_id.properties @@ -330,6 +330,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=Area yang ditandai t HTML\ table=Tabel HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Tabel HTML (dengan Abstrak dan BibTeX) + Icon=Ikon Ignore=Abaikan @@ -751,6 +752,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Sintaks yang diha User-specific\ file\ directory=Direktori berkas khusus pengguna + Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Nama isian otomatis hanya untuk format 'Namadepan Namaakhir' Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Nama isian otomatis hanya untuk format 'Namaakhir, Namadepan' Autocomplete\ names\ in\ both\ formats=Nama isian otomatis untuk kedua format diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 9151455d45e..21107c8ac9d 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -466,6 +466,8 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=L'area marcata non c HTML\ table=Tabella HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Tabella HTML (con Sommario e BibTeX) +Markdown\ titles=Titoli Markdown + Icon=Icona Ignore=Ignora @@ -1059,6 +1061,8 @@ Expected\ syntax\ for\ --fetch\='\:'=Sintassi attesa p Library-specific\ file\ directory=Directory file specifica della libreria User-specific\ file\ directory=Cartella dei file specifica dell'utente LaTeX\ file\ directory=Cartella dei file LaTeX +Path\ %0\ could\ not\ be\ resolved.\ Using\ working\ dir.=Il percorso %0 non può essere risolto. Utilizzo della directory di lavoro. + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=È necessario immettere un valore intero nell'intervallo 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Autocompletamento dei nomi solo nel formato 'Firstname Lastname' @@ -1485,6 +1489,14 @@ HTML\ to\ LaTeX=Da HTML a LaTeX LaTeX\ cleanup=Pulisci il LaTeX LaTeX\ to\ Unicode=Da LaTeX a Unicode lower\ case=minuscolo +Camel\ case=Notazione a cammello +Camel\ case\ -\ n\ letters\ max= Notazione a cammello\nNotazione a cammello - n massimo di lettere +Very\ short\ title=Titolo molto breve +Short\ title=Titolo breve +Returns\ first\ word\ of\ the\ title\ ignoring\ any\ function\ words.=Restituisce la prima parola del titolo ignorando qualsiasi parola di funzione. +Returns\ first\ 3\ words\ of\ the\ title\ ignoring\ any\ function\ words.=Restituisce le prime 3 parole del titolo ignorando qualsiasi parola di funzione. +Returns\ capitalized\ and\ concatenated\ title\ to\ N\ length.=Restituisce il titolo in maiuscolo e concatenato a lunghezza N. +Returns\ capitalized\ and\ concatenated\ title.=Restituisce il titolo in maiuscolo e concatenato. Minify\ list\ of\ person\ names=Riduci la lista di nomi di persona Normalize\ date=Normalizza la data Normalize\ en\ dashes=Normalizza trattini brevi @@ -1644,7 +1656,7 @@ Found\ overlapping\ ranges=Trovati intervalli di sovrapposizione Found\ touching\ ranges=Trovati intervalli di contatto Note\:\ Use\ the\ placeholder\ %DIR%\ for\ the\ location\ of\ the\ opened\ library\ file.=Nota\: Usa il segnaposto %DIR% per la posizione del file libreria aperto. -Error\ occurred\ while\ executing\ the\ command\ "%0".=Si è verificato un errore durante l'esecuzione del comando "%0". +Error\ occurred\ while\ executing\ the\ command\ "%0".=Si è verificato un errore durante l'esecuzione del comando \"%0\". Reformat\ ISSN=Riformatta ISSN Computer\ science=Informatica diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 7071b2d9662..a464ce87eeb 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -390,6 +390,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=標識した領域 HTML\ table=HTMLテーブル HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTMLテーブル(Abstract及びBibTeX付き) + Icon=アイコン Ignore=無視 @@ -911,6 +912,7 @@ Expected\ syntax\ for\ --fetch\='\:'=--fetch\='<取得 User-specific\ file\ directory=ユーザーファイルディレクトリ LaTeX\ file\ directory=LaTeXファイルディレクトリ + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=1025〜65535の間の整数値を入力しなくてはなりません Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=「名 姓」形式の名前のみ自動補完 Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=「姓, 名」形式の名前のみ自動補完 diff --git a/src/main/resources/l10n/JabRef_ko.properties b/src/main/resources/l10n/JabRef_ko.properties index 8e395560bf8..80058bd0ff2 100644 --- a/src/main/resources/l10n/JabRef_ko.properties +++ b/src/main/resources/l10n/JabRef_ko.properties @@ -370,6 +370,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=표시된 영역에 HTML\ table=HTML 테이블 HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML 테이블(Abstract & BibTeX 포함) + Icon=아이콘 Ignore=무시 @@ -863,6 +864,7 @@ Expected\ syntax\ for\ --fetch\='\:'=--fetch\='<페처 User-specific\ file\ directory=사용자별 파일 디렉토리 LaTeX\ file\ directory=LaTeX 파일 디렉토리 + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=1025-65535 간격으로 정수 값을 입력해야 합니다. Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only='이름 성' 형식의 이름만 자동 완성 Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only='성, 이름' 형식의 이름만 자동 완성 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 0cf1de57a77..e23fb5e1a45 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -397,6 +397,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=Het gemarkeerde gebi HTML\ table=HTML tabel HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML tabel (met Abstract & BibTeX) + Icon=Icoon Ignore=Negeren @@ -943,6 +944,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Verwachte syntax User-specific\ file\ directory=Gebruiker-specifieke map LaTeX\ file\ directory=LaTeX bestandsmap + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=U moet een integerwaarde invoeren in het interval 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Vul namen in de vorm 'Voornaam Achternaam' formaat automatisch in Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Vul namen in de vorm 'Achternaam, Voornaam' formaat automatisch in @@ -1515,7 +1517,7 @@ Found\ overlapping\ ranges=Overlappende bereiken gevonden Found\ touching\ ranges=Aangrenzende bereiken gevonden Note\:\ Use\ the\ placeholder\ %DIR%\ for\ the\ location\ of\ the\ opened\ library\ file.=Opmerking\: Gebruik de placeholder %DIR% voor de locatie van het geopende bibliotheekbestand. -Error\ occurred\ while\ executing\ the\ command\ "%0".=Fout opgetreden tijdens het uitvoeren van de opdracht "%0". +Error\ occurred\ while\ executing\ the\ command\ "%0".=Fout opgetreden tijdens het uitvoeren van de opdracht \"%0\". Reformat\ ISSN=ISSN formatteren Computer\ science=Informatica diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index d7d2f0aea26..861c41de911 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -305,6 +305,7 @@ Empty\ Underline=Tom understreking HTML\ table=HTML-tabell HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML-tabell (med Abstract & BibTeX) + Icon=Ikon Ignore=Ignorer @@ -717,6 +718,7 @@ Optional\ fields\ 2=Valgfrie felter 2 User-specific\ file\ directory=Brukerdefinert filkatalog + Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Autokompletter navn i 'Fornavn Etternavn'-format Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Autokompletter navn i 'Etternavn, Fornavn'-format Autocomplete\ names\ in\ both\ formats=Autokompletter navn i begge format diff --git a/src/main/resources/l10n/JabRef_pl.properties b/src/main/resources/l10n/JabRef_pl.properties index 11da1bb4b10..ec569378375 100644 --- a/src/main/resources/l10n/JabRef_pl.properties +++ b/src/main/resources/l10n/JabRef_pl.properties @@ -424,6 +424,8 @@ Empty\ Highlight=Puste podświetlenie HTML\ table=Tabela HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Tabela HTML (z Abstraktem i BibTeX) +Markdown\ titles=Tytuły Markdown + Icon=Ikona Ignore=Ignoruj @@ -990,6 +992,8 @@ Find\ and\ remove\ duplicate\ citation\ keys=Znajdź i usuń zduplikowane klucze Library-specific\ file\ directory=Katalog plików związanych z biblioteką User-specific\ file\ directory=Katalog plików użytkownika LaTeX\ file\ directory=Katalog plików LaTeX +Path\ %0\ could\ not\ be\ resolved.\ Using\ working\ dir.=Ścieżka %0 nie może zostać rozwiązana. Korzystanie z dziennika roboczego. + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=Musisz podać liczbę całkowitą z przedziału 1025-65535 Send=Wyślij @@ -1306,6 +1310,10 @@ Converts\ units\ to\ LaTeX\ formatting.=Konwertuje jednostki na formatowanie LaT HTML\ to\ LaTeX=HTML do LaTeX LaTeX\ cleanup=Czyszczenie LaTeX lower\ case=małe litery +Camel\ case=Notacja camelCase +Camel\ case\ -\ n\ letters\ max= Notacja camelCase - maksymalnie n liter +Very\ short\ title=Tytuł bardzo skrócony +Short\ title=Tytuł skrócony Normalize\ date=Normalizuj datę Normalize\ month=Normalizuj miesiąc Remove\ word\ enclosing\ braces=Usuń nawiasy otaczające słowo diff --git a/src/main/resources/l10n/JabRef_pt.properties b/src/main/resources/l10n/JabRef_pt.properties index 9971e8a6a3a..fc15e565056 100644 --- a/src/main/resources/l10n/JabRef_pt.properties +++ b/src/main/resources/l10n/JabRef_pt.properties @@ -377,6 +377,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=A área assinalada n HTML\ table=Tabela HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Tabela HTML ( com resumo (abstract) & BibTeX) + Icon=Ícone Ignore=Ignorar @@ -851,6 +852,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Sintaxe esperada User-specific\ file\ directory=Diretório de arquivo específico do usuário + Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Autocompletar nome em um formato 'Nome, Sobrenome' apenas Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Autocompletar nomes em um formato 'Sobrenome, Nome' apenas Autocomplete\ names\ in\ both\ formats=Autocompletar nomes em ambos os formatos diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index be1385e4085..42f2473b5af 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -465,6 +465,8 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=A área assinalada n HTML\ table=Tabela HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Tabela HTML ( com resumo (abstract) & BibTeX) +Markdown\ titles=Títulos Markdown + Icon=Ícone Ignore=Ignorar @@ -1056,6 +1058,8 @@ Expected\ syntax\ for\ --fetch\='\:'=Sintaxe esperada Library-specific\ file\ directory=Diretório de arquivos específicos da biblioteca User-specific\ file\ directory=Diretório de arquivo específico do usuário LaTeX\ file\ directory=Diretório de arquivos LaTeX +Path\ %0\ could\ not\ be\ resolved.\ Using\ working\ dir.=Caminho %0 não pode ser resolvido. Usando o diretório de trabalho. + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=Você deve digitar um valor inteiro no intervalo 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Autocompletar nome em um formato 'Nome, Sobrenome' apenas @@ -1482,6 +1486,14 @@ HTML\ to\ LaTeX=HTML para LaTeX LaTeX\ cleanup=Limpar LaTeX (cleanup) LaTeX\ to\ Unicode=LaTeX para Unicode lower\ case=minúsculas +Camel\ case=Camel case +Camel\ case\ -\ n\ letters\ max= Camel case - máx n letras +Very\ short\ title=Título muito curto +Short\ title=Título curto +Returns\ first\ word\ of\ the\ title\ ignoring\ any\ function\ words.=Retorna a primeira palavra do título ignorando quaisquer palavras de função. +Returns\ first\ 3\ words\ of\ the\ title\ ignoring\ any\ function\ words.=Retorna as primeiras 3 palavras do título ignorando quaisquer palavras de função. +Returns\ capitalized\ and\ concatenated\ title\ to\ N\ length.=Retorna capitalizado e concatenado o título até o comprimento N. +Returns\ capitalized\ and\ concatenated\ title.=Retorna capitalizado e concatenado o título. Minify\ list\ of\ person\ names=Minimizar lista de nomes de pessoas Normalize\ date=Normalizar a data Normalize\ en\ dashes=Normalizar "en dashes" diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index c0b44f18daa..bd6d0e3f2ac 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -403,6 +403,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=Выделенная HTML\ table=Таблица HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Таблица HTML (с резюме & BibTeX) + Icon=Значок Ignore=Пропуск @@ -929,6 +930,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Стандарт User-specific\ file\ directory=Пользовательский каталог файлов LaTeX\ file\ directory=Папка с файлами LaTeX + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=Необходимо ввести целое число в интервале 1025-65535 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Автозавершение имен только для формата 'Имя Фамилия' Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Автозавершение имен только для формата 'Фамилия, Имя' diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index bddb5ad12ce..b67a954b8a1 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -355,6 +355,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=Det markerade områd HTML\ table=HTML-tabell HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML-tabell (med Abstrakt och BibTeX-post) + Icon=Ikon Ignore=Ignorera @@ -775,6 +776,7 @@ Find\ and\ remove\ duplicate\ citation\ keys=Hitta och ta bort dubbla referensny User-specific\ file\ directory=Användarspecifik filmapp + Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Komplettera enbart namn i 'Förnamn Efternamn'-format Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Komplettera enbart namn i 'Efternamn, Förnamn'-format Autocomplete\ names\ in\ both\ formats=Komplettera namn automatiskt i bägge formaten diff --git a/src/main/resources/l10n/JabRef_tl.properties b/src/main/resources/l10n/JabRef_tl.properties index 03eb0060e63..0d98b17e7e3 100644 --- a/src/main/resources/l10n/JabRef_tl.properties +++ b/src/main/resources/l10n/JabRef_tl.properties @@ -304,6 +304,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=Ang may marka na lug HTML\ table=Talahanayan ng HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Talahanayan ng HTML (may Abstract at BibTeX) + Icon=Icon Ignore=I-ignore @@ -716,6 +717,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Inaasahang syntax User-specific\ file\ directory=Direktoryo ng file tukoy sa gumagamit + Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=Awtomatikong isali ang mga pangalan sa format ng 'Firstname Lastname' Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=Awtomatikong isali ang mga pangalan sa format ng 'Firstname Lastname' lamang Autocomplete\ names\ in\ both\ formats=Mga pangalan ng autocomplete sa parehong mga format diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index f6241c68cb3..91e6a2b52ab 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -412,6 +412,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=İşaretlenmiş alan HTML\ table=HTML tablosu HTML\ table\ (with\ Abstract\ &\ BibTeX)=(Özet & BibTeX ile) HTML tablosu + Icon=Simge Ignore=Yoksay @@ -965,6 +966,7 @@ Expected\ syntax\ for\ --fetch\='\:'=--fetch için bek User-specific\ file\ directory=Kullanıcıya özel dosya dizini LaTeX\ file\ directory=LaTeX dosya dizini + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=1025-65535 aralığında bir tam sayı değeri girmelisiniz Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=İsimleri yalnızca 'Ad Soyad' biçiminde otomatik tamamla Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=İsimleri yalnızca 'Soyad, Ad' biçiminde otomatik tamamla diff --git a/src/main/resources/l10n/JabRef_uk.properties b/src/main/resources/l10n/JabRef_uk.properties index d06e34795db..14dfc677902 100644 --- a/src/main/resources/l10n/JabRef_uk.properties +++ b/src/main/resources/l10n/JabRef_uk.properties @@ -514,6 +514,8 @@ Current\ value\:\ %0=Поточне значення\: %0 + + diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index e2dfb886985..f8e2d0e6a21 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -313,6 +313,7 @@ Empty\ Underline=Xóa phần gạch dưới HTML\ table=Bảng HTML HTML\ table\ (with\ Abstract\ &\ BibTeX)=Bảng HTML (với Tóm tắt & BibTeX) + Icon=Biểu tượng Ignore=Bỏ qua @@ -714,6 +715,7 @@ Expected\ syntax\ for\ --fetch\='\:'=Cú pháp mong đ User-specific\ file\ directory=Thư mục tập tin của người sử dụng cụ thể + Connecting...=Đang kết nối... diff --git a/src/main/resources/l10n/JabRef_zh_CN.properties b/src/main/resources/l10n/JabRef_zh_CN.properties index d9803cbca90..93e44eabe76 100644 --- a/src/main/resources/l10n/JabRef_zh_CN.properties +++ b/src/main/resources/l10n/JabRef_zh_CN.properties @@ -397,6 +397,7 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text\!=标注区域不包 HTML\ table=HTML 表 HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML 表(包含摘要和 BibTeX) + Icon=图标 Ignore=忽略 @@ -934,6 +935,7 @@ Expected\ syntax\ for\ --fetch\='\:'=期望的语法 - User-specific\ file\ directory=用户指定的文件目录 LaTeX\ file\ directory=LaTeX 文件目录 + You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=请输入一个 1025-65535 之间的整数值 Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=仅自动补全形如 'Firstname Lastname' 格式的姓名 Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=仅自动补全形如 'Lastname, Firstname' 格式的姓名 @@ -1504,7 +1506,7 @@ Found\ overlapping\ ranges=Found overlapping ranges Found\ touching\ ranges=Found touching ranges Note\:\ Use\ the\ placeholder\ %DIR%\ for\ the\ location\ of\ the\ opened\ library\ file.=Note\: Use the placeholder %DIR% for the location of the opened library file. -Error\ occurred\ while\ executing\ the\ command\ "%0".=执行 "%0" 命令时出错 +Error\ occurred\ while\ executing\ the\ command\ "%0".=执行 \"%0\" 命令时出错 Reformat\ ISSN=重新格式化 ISSN Computer\ science=计算机科学 diff --git a/src/main/resources/l10n/JabRef_zh_TW.properties b/src/main/resources/l10n/JabRef_zh_TW.properties index 706f0e1f4b0..17435bc03a6 100644 --- a/src/main/resources/l10n/JabRef_zh_TW.properties +++ b/src/main/resources/l10n/JabRef_zh_TW.properties @@ -307,6 +307,7 @@ Empty\ Underline=清除底線 HTML\ table=HTML 表格 HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML 表格(包含摘要和 BibTeX) + Icon=圖示 Ignore=忽略 @@ -628,6 +629,7 @@ Find\ and\ remove\ duplicate\ citation\ keys=查找並移除重複的引用鍵 ( LaTeX\ file\ directory=LaTeX 檔案目錄 + Autocomplete\ names\ in\ 'Firstname\ Lastname'\ format\ only=僅自動補全形如 'Firstname Lastname' 的姓名格式 Autocomplete\ names\ in\ 'Lastname,\ Firstname'\ format\ only=僅自動補全形如 'Lastname, Firstname' 的姓名格式 Autocomplete\ names\ in\ both\ formats=自動補全兩種姓名格式 diff --git a/src/main/resources/resource/layout/title-markdown/title-md.article.layout b/src/main/resources/resource/layout/title-markdown/title-md.article.layout new file mode 100644 index 00000000000..bd491638613 --- /dev/null +++ b/src/main/resources/resource/layout/title-markdown/title-md.article.layout @@ -0,0 +1 @@ +* \format[RemoveLatexCommands,HTMLChars]{\title}. \begin{journal}\format[RemoveLatexCommands,HTMLChars]{\journal}\end{journal}\begin{year} \format{\year}\end{year} diff --git a/src/main/resources/resource/layout/title-markdown/title-md.book.layout b/src/main/resources/resource/layout/title-markdown/title-md.book.layout new file mode 100644 index 00000000000..c136fa5fa3d --- /dev/null +++ b/src/main/resources/resource/layout/title-markdown/title-md.book.layout @@ -0,0 +1 @@ +* \format[RemoveLatexCommands,HTMLChars]{\title}.\begin{publisher} \format[RemoveLatexCommands,HTMLChars]{\publisher}\end{publisher} \format{\year}\end{year} diff --git a/src/main/resources/resource/layout/title-markdown/title-md.incollection.layout b/src/main/resources/resource/layout/title-markdown/title-md.incollection.layout new file mode 100644 index 00000000000..66a1528b0bc --- /dev/null +++ b/src/main/resources/resource/layout/title-markdown/title-md.incollection.layout @@ -0,0 +1 @@ +* \format[RemoveLatexCommands,HTMLChars]{\title}. \begin{booktitle}\format[RemoveLatexCommands,HTMLChars]{\booktitle}\end{booktitle}\begin{publisher}, \format[RemoveLatexCommands,HTMLChars]{\publisher}\end{publisher} \format{\year} diff --git a/src/main/resources/resource/layout/title-markdown/title-md.inproceedings.layout b/src/main/resources/resource/layout/title-markdown/title-md.inproceedings.layout new file mode 100644 index 00000000000..1d16d1eb94f --- /dev/null +++ b/src/main/resources/resource/layout/title-markdown/title-md.inproceedings.layout @@ -0,0 +1 @@ +* \format[RemoveLatexCommands,HTMLChars]{\title}. \begin{publisher}\format[RemoveLatexCommands,HTMLChars]{\publisher} \end{publisher}\begin{series}\format[RemoveLatexCommands,HTMLChars]{\series}\end{series}\begin{!series}\format[RemoveLatexCommands,HTMLChars]{\booktitle} \format{\year}\end{!series} diff --git a/src/main/resources/resource/layout/title-markdown/title-md.layout b/src/main/resources/resource/layout/title-markdown/title-md.layout new file mode 100644 index 00000000000..4fa6ad3e417 --- /dev/null +++ b/src/main/resources/resource/layout/title-markdown/title-md.layout @@ -0,0 +1 @@ +* \format[RemoveLatexCommands,HTMLChars]{\title}.\begin{year} \year\end{year} diff --git a/src/test/java/org/jabref/architecture/MainArchitectureTest.java b/src/test/java/org/jabref/architecture/MainArchitectureTest.java index 1c5fd478d18..476fc088ab8 100644 --- a/src/test/java/org/jabref/architecture/MainArchitectureTest.java +++ b/src/test/java/org/jabref/architecture/MainArchitectureTest.java @@ -1,5 +1,6 @@ package org.jabref.architecture; +import java.net.URI; import java.nio.file.Paths; import org.jabref.logic.importer.fileformat.ImporterTestEngine; @@ -15,7 +16,6 @@ /** * This class checks JabRef's shipped classes for architecture quality. - * * Does not analyze test classes. Hint from StackOverflow */ @AnalyzeClasses(packages = "org.jabref", importOptions = ImportOption.DoNotIncludeTests.class) @@ -150,4 +150,13 @@ public void restrictStandardStreams(JavaClasses classes) { .because("logging framework should be used instead or the class be marked explicitly as @AllowedToUseStandardStreams") .check(classes); } + + @ArchTest + public void shouldNotCallUriCreateMethod(JavaClasses classes) { + noClasses() + .that() + .resideInAPackage("org.jabref..") + .should().callMethod(URI.class, "create", String.class) + .check(classes); + } } diff --git a/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java b/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java index 04295b6cb4c..765042e5dc5 100644 --- a/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java +++ b/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java @@ -5,7 +5,6 @@ import java.net.CookieManager; import java.net.CookiePolicy; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -27,6 +26,7 @@ import org.jabref.logic.externalfiles.LinkedFileHandler; import org.jabref.logic.util.CurrentThreadTaskExecutor; import org.jabref.logic.util.TaskExecutor; +import org.jabref.logic.util.URLUtil; import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -198,7 +198,7 @@ void downloadHtmlFileCausesWarningDisplay(Boolean keepHtmlLink, String warningTe when(filePreferences.getFileDirectoryPattern()).thenReturn("[entrytype]"); databaseContext.setDatabasePath(tempFile); - URL url = URI.create("https://www.google.com/").toURL(); + URL url = URLUtil.create("https://www.google.com/"); String fileType = StandardExternalFileType.URL.getName(); linkedFile = new LinkedFile(url, fileType); @@ -275,7 +275,7 @@ void mimeTypeStringWithParameterIsReturnedAsWithoutParameter() { @ParameterizedTest @ValueSource(booleans = {true, false}) void downloadPdfFileWhenLinkedFilePointsToPdfUrl(boolean keepHtml) throws MalformedURLException { - linkedFile = new LinkedFile(URI.create("http://arxiv.org/pdf/1207.0408v1").toURL(), "pdf"); + linkedFile = new LinkedFile(URLUtil.create("http://arxiv.org/pdf/1207.0408v1"), "pdf"); // Needed Mockito stubbing methods to run test when(filePreferences.shouldStoreFilesRelativeToBibFile()).thenReturn(true); when(filePreferences.getFileNamePattern()).thenReturn("[citationkey]"); diff --git a/src/test/java/org/jabref/gui/linkedfile/DownloadLinkedFileActionTest.java b/src/test/java/org/jabref/gui/linkedfile/DownloadLinkedFileActionTest.java index b7ab54475ee..17e4aa28af1 100644 --- a/src/test/java/org/jabref/gui/linkedfile/DownloadLinkedFileActionTest.java +++ b/src/test/java/org/jabref/gui/linkedfile/DownloadLinkedFileActionTest.java @@ -3,7 +3,6 @@ import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookiePolicy; -import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -18,6 +17,7 @@ import org.jabref.gui.preferences.GuiPreferences; import org.jabref.logic.FilePreferences; import org.jabref.logic.util.CurrentThreadTaskExecutor; +import org.jabref.logic.util.URLUtil; import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -93,7 +93,7 @@ void tearDown() { void replacesLinkedFiles(@TempDir Path tempFolder) throws Exception { String url = "http://arxiv.org/pdf/1207.0408v1"; - LinkedFile linkedFile = new LinkedFile(URI.create(url).toURL(), ""); + LinkedFile linkedFile = new LinkedFile(URLUtil.create(url), ""); when(databaseContext.getFirstExistingFileDir(any())).thenReturn(Optional.of(tempFolder)); when(filePreferences.getFileNamePattern()).thenReturn("[citationkey]"); when(filePreferences.getFileDirectoryPattern()).thenReturn(""); @@ -118,7 +118,7 @@ void replacesLinkedFiles(@TempDir Path tempFolder) throws Exception { void doesntReplaceSourceURL(boolean keepHtml) throws Exception { String url = "http://arxiv.org/pdf/1207.0408v1"; - LinkedFile linkedFile = new LinkedFile(URI.create(url).toURL(), ""); + LinkedFile linkedFile = new LinkedFile(URLUtil.create(url), ""); when(databaseContext.getFirstExistingFileDir(any())).thenReturn(Optional.of(tempFolder)); when(filePreferences.getFileNamePattern()).thenReturn("[citationkey]"); when(filePreferences.getFileDirectoryPattern()).thenReturn(""); @@ -173,7 +173,7 @@ void keepsHtmlFileLink(@TempDir Path tempFolder) throws Exception { .withStatus(200) .withHeader("Content-Type", "text/html; charset=utf-8"))); - LinkedFile linkedFile = new LinkedFile(URI.create("http://localhost:2331/html").toURL(), ""); + LinkedFile linkedFile = new LinkedFile(URLUtil.create("http://localhost:2331/html"), ""); when(databaseContext.getFirstExistingFileDir(any())).thenReturn(Optional.of(tempFolder)); when(filePreferences.getFileNamePattern()).thenReturn("[citationkey]"); when(filePreferences.getFileDirectoryPattern()).thenReturn(""); @@ -209,7 +209,7 @@ void removesHtmlFileLink(@TempDir Path tempFolder) throws Exception { .withStatus(200) .withHeader("Content-Type", "text/html; charset=utf-8"))); - LinkedFile linkedFile = new LinkedFile(URI.create("http://localhost:2331/html").toURL(), ""); + LinkedFile linkedFile = new LinkedFile(URLUtil.create("http://localhost:2331/html"), ""); when(databaseContext.getFirstExistingFileDir(any())).thenReturn(Optional.of(tempFolder)); when(filePreferences.getFileNamePattern()).thenReturn("[citationkey]"); when(filePreferences.getFileDirectoryPattern()).thenReturn(""); diff --git a/src/test/java/org/jabref/gui/linkedfile/LinkedFileEditDialogViewModelTest.java b/src/test/java/org/jabref/gui/linkedfile/LinkedFileEditDialogViewModelTest.java new file mode 100644 index 00000000000..d19c5d9cbb0 --- /dev/null +++ b/src/test/java/org/jabref/gui/linkedfile/LinkedFileEditDialogViewModelTest.java @@ -0,0 +1,55 @@ +package org.jabref.gui.linkedfile; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.TreeSet; + +import javafx.collections.FXCollections; + +import org.jabref.gui.DialogService; +import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.gui.frame.ExternalApplicationsPreferences; +import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.FilePreferences; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.LinkedFile; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Answers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class LinkedFileEditDialogViewModelTest { + private final GuiPreferences preferences = mock(GuiPreferences.class, Answers.RETURNS_DEEP_STUBS); + private final FilePreferences filePreferences = mock(FilePreferences.class, Answers.RETURNS_DEEP_STUBS); + private final BibDatabaseContext bibDatabaseContext = mock(BibDatabaseContext.class); + private final DialogService dialogService = mock(DialogService.class); + private final ExternalApplicationsPreferences externalApplicationsPreferences = mock(ExternalApplicationsPreferences.class); + + @BeforeEach + void setup() { + when(externalApplicationsPreferences.getExternalFileTypes()).thenReturn(FXCollections.observableSet(new TreeSet<>(ExternalFileTypes.getDefaultExternalFileTypes()))); + when(preferences.getExternalApplicationsPreferences()).thenReturn(externalApplicationsPreferences); + when(preferences.getFilePreferences()).thenReturn(filePreferences); + } + + @Test + void badFilenameCharWillBeReplacedByUnderscore(@TempDir Path tempDir) throws Exception { + + Path invalidFile = tempDir.resolve("?invalid.pdf"); + Files.createFile(invalidFile); + when(dialogService.showConfirmationDialogAndWait(any(), any(), any())).thenReturn(true); + + LinkedFileEditDialogViewModel viewModel = new LinkedFileEditDialogViewModel(new LinkedFile("", "", ""), bibDatabaseContext, dialogService, externalApplicationsPreferences, filePreferences); + + viewModel.checkForBadFileNameAndAdd(invalidFile); + + LinkedFile expectedFile = new LinkedFile("", tempDir.resolve("_invalid.pdf").toString(), "PDF"); + assertEquals(expectedFile, viewModel.getNewLinkedFile()); + } +} diff --git a/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java b/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java index e7b9e643db5..111858ea386 100644 --- a/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java +++ b/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java @@ -584,6 +584,75 @@ void expandBracketsDoesNotTruncateWithoutAnArgumentToTruncateModifier() { BracketedPattern.expandBrackets("[fulltitle:truncate]", ';', dbentry, database)); } + /** + * Test the [:camel] modifier + */ + @ParameterizedTest + @CsvSource({ + "'CamelTitleFormatter', 'Camel Title Formatter'", + "'CamelTitleFormatter', 'CAMEL TITLE FORMATTER'", + "'CamelTitleFormatter', 'camel title formatter'", + "'CamelTitleFormatter', 'cAMEL tITLE fORMATTER'", + "'C', 'c'" + }) + + void expandBracketsCamelTitleModifier(String expectedCitationKey, String title) { + BibEntry bibEntry = new BibEntry() + .withField(StandardField.TITLE, title); + assertEquals(expectedCitationKey, + BracketedPattern.expandBrackets("[title:camel]", ';', bibEntry, null)); + } + + /** + * Test the [:veryshorttitle] modifier + */ + @ParameterizedTest + @CsvSource({ + "'Very', 'A very short title'", + "'V', 'V'", + "'V', 'A v'" + }) + + void expandBracketsVeryShortTitleModifier(String expectedCitationKey, String title) { + BibEntry bibEntry = new BibEntry() + .withField(StandardField.TITLE, title); + assertEquals(expectedCitationKey, + BracketedPattern.expandBrackets("[title:veryshorttitle]", ';', bibEntry, null)); + } + + /** + * Test the [:shorttitle] modifier + */ + @ParameterizedTest + @CsvSource({ + "'Very Short Title', 'A very short title'", + "'Short Title', 'Short title'", + "'Title', 'A title'", + "'Title', 'A Title'" + }) + + void expandBracketsShortTitleModifier(String expectedCitationKey, String title) { + BibEntry bibEntry = new BibEntry() + .withField(StandardField.TITLE, title); + assertEquals(expectedCitationKey, + BracketedPattern.expandBrackets("[title:shorttitle]", ';', bibEntry, null)); + } + + /** + * Test the [:camelN] modifier + */ + @Test + void expandBracketsCamelNModifier() { + BibEntry bibEntry = new BibEntry() + .withField(StandardField.TITLE, "Open Source Software And The Private Collective Innovation Model Issues"); + assertEquals("Open", + BracketedPattern.expandBrackets("[title:camel1]", ';', bibEntry, null)); + assertEquals("OpenSourceSoftwareAnd", + BracketedPattern.expandBrackets("[title:camel4]", ';', bibEntry, null)); + assertEquals("OpenSourceSoftwareAndThePrivateCollectiveInnovationModelIssues", + BracketedPattern.expandBrackets("[title:camel10]", ';', bibEntry, null)); + } + /** * Test the [camelN] title marker. */ diff --git a/src/test/java/org/jabref/logic/exporter/MarkdownTitleExporterTest.java b/src/test/java/org/jabref/logic/exporter/MarkdownTitleExporterTest.java new file mode 100644 index 00000000000..19ae753ef15 --- /dev/null +++ b/src/test/java/org/jabref/logic/exporter/MarkdownTitleExporterTest.java @@ -0,0 +1,192 @@ +package org.jabref.logic.exporter; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import org.jabref.logic.layout.LayoutFormatterPreferences; +import org.jabref.logic.util.StandardFileType; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.types.StandardEntryType; +import org.jabref.model.metadata.SaveOrder; +import org.jabref.model.metadata.SelfContainedSaveOrder; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Answers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +class MarkdownTitleExporterTest { + + private static Exporter htmlWebsiteExporter; + private static BibDatabaseContext databaseContext; + private static final SelfContainedSaveOrder SAVE_MOST_RECENT_FIRST_SAVE_ORDER = new SelfContainedSaveOrder(SaveOrder.OrderType.SPECIFIED, List.of(new SaveOrder.SortCriterion(StandardField.YEAR, true))); + + @BeforeAll + static void setUp() { + htmlWebsiteExporter = new TemplateExporter( + "Title-Markdown", + "title-md", + "title-md", + "title-markdown", + StandardFileType.MARKDOWN, + mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS), + SAVE_MOST_RECENT_FIRST_SAVE_ORDER, + BlankLineBehaviour.DELETE_BLANKS); + + databaseContext = new BibDatabaseContext(); + } + + @Test + final void exportForNoEntriesWritesNothing(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("ThisIsARandomlyNamedFile"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, tempDir, Collections.emptyList()); + assertEquals(Collections.emptyList(), Files.readAllLines(file)); + } + + @Test + final void exportsCorrectContentArticle(@TempDir Path tempDir) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.Article) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.JOURNAL, "Journal of this \\& that") + .withField(StandardField.PUBLISHER, "THE PRESS") + .withField(StandardField.YEAR, "2020"); + + Path file = tempDir.resolve("RandomFileName"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry)); + + List expected = List.of( + "* Test Title. Journal of this & that 2020"); + + assertEquals(expected, Files.readAllLines(file)); + } + + @Test + final void exportsCorrectContentInCollection(@TempDir Path tempDir) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.InCollection) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.BOOKTITLE, "Test book") + .withField(StandardField.PUBLISHER, "PRESS") + .withField(StandardField.YEAR, "2020"); + + Path file = tempDir.resolve("RandomFileName"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry)); + + List expected = List.of( + "* Test Title. Test book, PRESS 2020"); + + assertEquals(expected, Files.readAllLines(file)); + } + + @Test + final void exportsCorrectContentBook(@TempDir Path tempDir) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.Book) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.BOOKTITLE, "Test book") + .withField(StandardField.PUBLISHER, "PRESS") + .withField(StandardField.YEAR, "2020"); + + Path file = tempDir.resolve("RandomFileName"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry)); + + List expected = List.of( + "* Test Title. PRESS 2020"); + + assertEquals(expected, Files.readAllLines(file)); + } + + @Test + final void exportsCorrectContentInProceeedingsPublisher(@TempDir Path tempDir) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.InProceedings) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.BOOKTITLE, "Test Conference") + .withField(StandardField.PUBLISHER, "ACM") + .withField(StandardField.SERIES, "CONF'20") + .withField(StandardField.YEAR, "2020"); + + Path file = tempDir.resolve("RandomFileName"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry)); + + List expected = List.of( + "* Test Title. ACM CONF'20"); + + assertEquals(expected, Files.readAllLines(file)); + } + + @Test + final void exportsCorrectContentInProceeedingsNoPublisher(@TempDir Path tempDir) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.InProceedings) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.BOOKTITLE, "Test Conference") + .withField(StandardField.SERIES, "CONF'20") + .withField(StandardField.YEAR, "2020"); + + Path file = tempDir.resolve("RandomFileName"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry)); + + List expected = List.of( + "* Test Title. CONF'20"); + + assertEquals(expected, Files.readAllLines(file)); + } + + @Test + final void exportsCorrectContentInProceeedingsNoSeries(@TempDir Path tempDir) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.InProceedings) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.BOOKTITLE, "Test Conference") + .withField(StandardField.YEAR, "2020"); + + Path file = tempDir.resolve("RandomFileName"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry)); + + List expected = List.of( + "* Test Title. Test Conference 2020"); + + assertEquals(expected, Files.readAllLines(file)); + } + + @Test + final void exportsCorrectContentBracketsInTitle(@TempDir Path tempDir) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.Article) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "This is {JabRef}") + .withField(StandardField.JOURNAL, "Journal of this \\& that") + .withField(StandardField.YEAR, "2020"); + + Path file = tempDir.resolve("RandomFileName"); + Files.createFile(file); + htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry)); + + List expected = List.of( + "* This is JabRef. Journal of this & that 2020"); + + assertEquals(expected, Files.readAllLines(file)); + } +} diff --git a/src/test/java/org/jabref/logic/help/HelpFileTest.java b/src/test/java/org/jabref/logic/help/HelpFileTest.java index 63be3fb2316..5c8abcae5d0 100644 --- a/src/test/java/org/jabref/logic/help/HelpFileTest.java +++ b/src/test/java/org/jabref/logic/help/HelpFileTest.java @@ -2,12 +2,12 @@ import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; import java.net.URL; import java.util.Arrays; import java.util.stream.Stream; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.URLUtil; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -25,7 +25,7 @@ static Stream getAllHelpFiles() { @ParameterizedTest @MethodSource("getAllHelpFiles") void referToValidPage(HelpFile help) throws IOException { - URL url = URI.create(jabrefHelp + help.getPageName()).toURL(); + URL url = URLUtil.create(jabrefHelp + help.getPageName()); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestProperty("User-Agent", URLDownload.USER_AGENT); assertEquals(200, http.getResponseCode(), "Wrong URL: " + url.toString()); diff --git a/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java b/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java index 7a9ecf1d031..275ccc59a56 100644 --- a/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java +++ b/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java @@ -2,12 +2,12 @@ import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; import java.util.Optional; import java.util.Set; import org.jabref.logic.importer.fetcher.TrustLevel; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.testutils.category.FetcherTest; @@ -33,7 +33,7 @@ default TrustLevel getTrustLevel() { @Test void acceptPdfUrls() throws MalformedURLException { - URL pdfUrl = URI.create("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf").toURL(); + URL pdfUrl = URLUtil.create("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); FulltextFetcherWithTrustLevel finder = e -> Optional.of(pdfUrl); FulltextFetchers fetcher = new FulltextFetchers(Set.of(finder)); assertEquals(Optional.of(pdfUrl), fetcher.findFullTextPDF(new BibEntry())); @@ -41,7 +41,7 @@ void acceptPdfUrls() throws MalformedURLException { @Test void rejectNonPdfUrls() throws MalformedURLException { - URL pdfUrl = URI.create("https://github.com/JabRef/jabref/blob/master/README.md").toURL(); + URL pdfUrl = URLUtil.create("https://github.com/JabRef/jabref/blob/master/README.md"); FulltextFetcherWithTrustLevel finder = e -> Optional.of(pdfUrl); FulltextFetchers fetcher = new FulltextFetchers(Set.of(finder)); @@ -50,7 +50,7 @@ void rejectNonPdfUrls() throws MalformedURLException { @Test void noTrustLevel() throws MalformedURLException { - URL pdfUrl = URI.create("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf").toURL(); + URL pdfUrl = URLUtil.create("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); FulltextFetcherWithTrustLevel finder = e -> Optional.of(pdfUrl); FulltextFetchers fetcher = new FulltextFetchers(Set.of(finder)); @@ -64,12 +64,12 @@ void higherTrustLevelWins() throws IOException, FetcherException { FulltextFetcher finderHigh = mock(FulltextFetcher.class); when(finderHigh.getTrustLevel()).thenReturn(TrustLevel.SOURCE); - final URL highUrl = URI.create("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf").toURL(); + final URL highUrl = URLUtil.create("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); when(finderHigh.findFullText(entry)).thenReturn(Optional.of(highUrl)); FulltextFetcher finderLow = mock(FulltextFetcher.class); when(finderLow.getTrustLevel()).thenReturn(TrustLevel.UNKNOWN); - final URL lowUrl = URI.create("http://docs.oasis-open.org/opencsa/sca-bpel/sca-bpel-1.1-spec-cd-01.pdf").toURL(); + final URL lowUrl = URLUtil.create("http://docs.oasis-open.org/opencsa/sca-bpel/sca-bpel-1.1-spec-cd-01.pdf"); when(finderLow.findFullText(entry)).thenReturn(Optional.of(lowUrl)); FulltextFetchers fetchers = new FulltextFetchers(Set.of(finderLow, finderHigh)); diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java index 71344372b5f..e3d230759bb 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java @@ -1,9 +1,9 @@ package org.jabref.logic.importer.fetcher; -import java.net.URI; import java.util.Optional; import org.jabref.logic.importer.FulltextFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.support.DisabledOnCIServer; @@ -23,7 +23,7 @@ void findByDOI() throws Exception { // DOI randomly chosen from https://pubs.acs.org/toc/acscii/0/0 BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1021/acscentsci.4c00971"); assertEquals( - Optional.of(URI.create("https://pubs.acs.org/doi/pdf/10.1021/acscentsci.4c00971").toURL()), + Optional.of(URLUtil.create("https://pubs.acs.org/doi/pdf/10.1021/acscentsci.4c00971")), fetcher.findFullText(entry) ); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java index a18cd2f7ed2..33d48b36583 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java @@ -1,8 +1,8 @@ package org.jabref.logic.importer.fetcher; -import java.net.URI; import java.util.Optional; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.testutils.category.FetcherTest; @@ -25,13 +25,13 @@ void setUp() { @Test void findFullTextFromDoi() throws Exception { BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1103/PhysRevLett.116.061102"); - assertEquals(Optional.of(URI.create("https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.116.061102").toURL()), finder.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.116.061102")), finder.findFullText(entry)); } @Test void findFullTextFromLowercaseDoi() throws Exception { BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1103/physrevlett.124.029002"); - assertEquals(Optional.of(URI.create("https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.124.029002").toURL()), finder.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.124.029002")), finder.findFullText(entry)); } @Test diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java index 68e6ae9115f..6552de6c279 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -16,6 +15,7 @@ import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.PagedSearchBasedFetcher; import org.jabref.logic.importer.SearchBasedFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.InternalField; @@ -198,19 +198,19 @@ void findFullTextByDOI() throws IOException { entry.setField(StandardField.DOI, "10.1529/biophysj.104.047340"); entry.setField(StandardField.TITLE, "Pause Point Spectra in DNA Constant-Force Unzipping"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/cond-mat/0406246v1").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/cond-mat/0406246v1")), fetcher.findFullText(entry)); } @Test void findFullTextByEprint() throws IOException { entry.setField(StandardField.EPRINT, "1603.06570"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/1603.06570v1").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/1603.06570v1")), fetcher.findFullText(entry)); } @Test void findFullTextByEprintWithPrefix() throws IOException { entry.setField(StandardField.EPRINT, "arXiv:1603.06570"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/1603.06570v1").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/1603.06570v1")), fetcher.findFullText(entry)); } @Test @@ -218,21 +218,21 @@ void findFullTextByEprintWithUnknownDOI() throws IOException { entry.setField(StandardField.DOI, "10.1529/unknown"); entry.setField(StandardField.EPRINT, "1603.06570"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/1603.06570v1").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/1603.06570v1")), fetcher.findFullText(entry)); } @Test void findFullTextByTitle() throws IOException { entry.setField(StandardField.TITLE, "Pause Point Spectra in DNA Constant-Force Unzipping"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/cond-mat/0406246v1").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/cond-mat/0406246v1")), fetcher.findFullText(entry)); } @Test void findFullTextByTitleWithCurlyBracket() throws IOException { entry.setField(StandardField.TITLE, "Machine versus {Human} {Attention} in {Deep} {Reinforcement} {Learning} {Tasks}"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/2010.15942v3").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/2010.15942v3")), fetcher.findFullText(entry)); } @Test @@ -240,7 +240,7 @@ void findFullTextByTitleWithColonAndJournalWithoutEprint() throws IOException { entry.setField(StandardField.TITLE, "Bayes-TrEx: a Bayesian Sampling Approach to Model Transparency by Example"); entry.setField(StandardField.JOURNAL, "arXiv:2002.10248v4 [cs]"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/2002.10248v4").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/2002.10248v4")), fetcher.findFullText(entry)); } @Test @@ -248,7 +248,7 @@ void findFullTextByTitleWithColonAndUrlWithoutEprint() throws IOException { entry.setField(StandardField.TITLE, "Bayes-TrEx: a Bayesian Sampling Approach to Model Transparency by Example"); entry.setField(StandardField.URL, "http://arxiv.org/abs/2002.10248v4"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/2002.10248v4").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/2002.10248v4")), fetcher.findFullText(entry)); } @Test @@ -256,7 +256,7 @@ void findFullTextByTitleAndPartOfAuthor() throws IOException { entry.setField(StandardField.TITLE, "Pause Point Spectra in DNA Constant-Force Unzipping"); entry.setField(StandardField.AUTHOR, "Weeks and Lucks"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/cond-mat/0406246v1").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/cond-mat/0406246v1")), fetcher.findFullText(entry)); } @Test @@ -264,7 +264,7 @@ void findFullTextByTitleWithCurlyBracketAndPartOfAuthor() throws IOException { entry.setField(StandardField.TITLE, "Machine versus {Human} {Attention} in {Deep} {Reinforcement} {Learning} {Tasks}"); entry.setField(StandardField.AUTHOR, "Zhang, Ruohan and Guo"); - assertEquals(Optional.of(URI.create("http://arxiv.org/pdf/2010.15942v3").toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("http://arxiv.org/pdf/2010.15942v3")), fetcher.findFullText(entry)); } @Test diff --git a/src/test/java/org/jabref/logic/importer/fetcher/CiteSeerTest.java b/src/test/java/org/jabref/logic/importer/fetcher/CiteSeerTest.java index 9ecb239e06f..22b929ab63e 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/CiteSeerTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/CiteSeerTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.net.URL; import java.util.Collections; import java.util.Iterator; @@ -9,6 +8,7 @@ import java.util.Optional; import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; @@ -101,7 +101,7 @@ void searchWithSortingByYearAndYearRange() throws FetcherException { void findByIdAsDOI() throws FetcherException, IOException { BibEntry entry = new BibEntry(StandardEntryType.Misc) .withField(StandardField.DOI, "c16e0888b17cb2c689e5dfa4e2be4fdffb23869e"); - Optional expected = Optional.of(URI.create("https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=c16e0888b17cb2c689e5dfa4e2be4fdffb23869e").toURL()); + Optional expected = Optional.of(URLUtil.create("https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=c16e0888b17cb2c689e5dfa4e2be4fdffb23869e")); assertEquals(expected, fetcher.findFullText(entry)); } @@ -110,7 +110,7 @@ void findBySourceURL() throws FetcherException, IOException { BibEntry entry = new BibEntry(StandardEntryType.Misc) .withField(StandardField.DOI, "") .withField(StandardField.URL, "http://intl.psychosomaticmedicine.org/content/55/3/234.full.pdf"); - Optional expected = Optional.of(URI.create("http://intl.psychosomaticmedicine.org/content/55/3/234.full.pdf").toURL()); + Optional expected = Optional.of(URLUtil.create("http://intl.psychosomaticmedicine.org/content/55/3/234.full.pdf")); assertEquals(expected, fetcher.findFullText(entry)); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/DoiResolutionTest.java b/src/test/java/org/jabref/logic/importer/fetcher/DoiResolutionTest.java index d66799df0bf..2feb88edb9d 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/DoiResolutionTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/DoiResolutionTest.java @@ -1,10 +1,10 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.util.Optional; import org.jabref.logic.preferences.DOIPreferences; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.testutils.category.FetcherTest; @@ -35,7 +35,7 @@ void setup() { void linkWithPdfInTitleTag() throws IOException { entry.setField(StandardField.DOI, "10.1051/0004-6361/201527330"); assertEquals( - Optional.of(URI.create("https://www.aanda.org/articles/aa/pdf/2016/01/aa27330-15.pdf").toURL()), + Optional.of(URLUtil.create("https://www.aanda.org/articles/aa/pdf/2016/01/aa27330-15.pdf")), finder.findFullText(entry) ); } @@ -44,13 +44,13 @@ void linkWithPdfInTitleTag() throws IOException { @Test void linkWithPdfStringLeadsToFulltext() throws IOException { entry.setField(StandardField.DOI, "10.1002/acr2.11101"); - assertEquals(Optional.of(URI.create("https://onlinelibrary.wiley.com/doi/pdf/10.1002/acr2.11101").toURL()), finder.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("https://onlinelibrary.wiley.com/doi/pdf/10.1002/acr2.11101")), finder.findFullText(entry)); } @Test void citationMetaTagLeadsToFulltext() throws IOException { entry.setField(StandardField.DOI, "10.1007/978-3-319-89963-3_28"); - assertEquals(Optional.of(URI.create("https://link.springer.com/content/pdf/10.1007/978-3-319-89963-3_28.pdf").toURL()), finder.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("https://link.springer.com/content/pdf/10.1007/978-3-319-89963-3_28.pdf")), finder.findFullText(entry)); } @Test @@ -65,7 +65,7 @@ void returnAnythingWhenBehindSpringerPayWall() throws IOException { // even if the user does not have access // We cannot easily handle this case, because other publisher return the wrong media type. entry.setField(StandardField.DOI, "10.1007/978-3-319-62594-2_12"); - assertEquals(Optional.of(URI.create("https://link.springer.com/content/pdf/10.1007/978-3-319-62594-2_12.pdf").toURL()), finder.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("https://link.springer.com/content/pdf/10.1007/978-3-319-62594-2_12.pdf")), finder.findFullText(entry)); } @Test diff --git a/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java b/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java index b8a26327f79..2c33a317d02 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -10,6 +9,7 @@ import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.PagedSearchBasedFetcher; import org.jabref.logic.importer.SearchBasedFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; @@ -42,7 +42,7 @@ void linkFound() throws Exception { entry.setField(StandardField.TITLE, "Towards Application Portability in Platform as a Service"); assertEquals( - Optional.of(URI.create("https://www.uni-bamberg.de/fileadmin/uni/fakultaeten/wiai_lehrstuehle/praktische_informatik/Dateien/Publikationen/sose14-towards-application-portability-in-paas.pdf").toURL()), + Optional.of(URLUtil.create("https://www.uni-bamberg.de/fileadmin/uni/fakultaeten/wiai_lehrstuehle/praktische_informatik/Dateien/Publikationen/sose14-towards-application-portability-in-paas.pdf")), finder.findFullText(entry) ); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/IEEETest.java b/src/test/java/org/jabref/logic/importer/fetcher/IEEETest.java index 60ae6d11a44..4d12cac558b 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/IEEETest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/IEEETest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fetcher; -import java.net.URI; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -11,6 +10,7 @@ import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.PagedSearchBasedFetcher; import org.jabref.logic.importer.SearchBasedFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; @@ -75,7 +75,7 @@ void setUp() { @Disabled("IEEE seems to block us") void findByDOI() throws Exception { BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1109/ACCESS.2016.2535486"); - assertEquals(Optional.of(URI.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=").toURL()), + assertEquals(Optional.of(URLUtil.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=")), fetcher.findFullText(entry)); } @@ -83,7 +83,7 @@ void findByDOI() throws Exception { @Disabled("IEEE seems to block us") void findByDocumentUrl() throws Exception { BibEntry entry = new BibEntry().withField(StandardField.URL, "https://ieeexplore.ieee.org/document/7421926/"); - assertEquals(Optional.of(URI.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=").toURL()), + assertEquals(Optional.of(URLUtil.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=")), fetcher.findFullText(entry)); } @@ -91,7 +91,7 @@ void findByDocumentUrl() throws Exception { @Disabled("IEEE seems to block us") void findByURL() throws Exception { BibEntry entry = new BibEntry().withField(StandardField.URL, "https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7421926&ref="); - assertEquals(Optional.of(URI.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=").toURL()), + assertEquals(Optional.of(URLUtil.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=")), fetcher.findFullText(entry)); } @@ -99,7 +99,7 @@ void findByURL() throws Exception { @Disabled("IEEE blocks us - works in browser") void findByOldURL() throws Exception { BibEntry entry = new BibEntry().withField(StandardField.URL, "https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=7421926"); - assertEquals(Optional.of(URI.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=").toURL()), + assertEquals(Optional.of(URLUtil.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=")), fetcher.findFullText(entry)); } @@ -109,7 +109,7 @@ void findByDOIButNotURL() throws Exception { BibEntry entry = new BibEntry() .withField(StandardField.DOI, "10.1109/ACCESS.2016.2535486") .withField(StandardField.URL, "http://dx.doi.org/10.1109/ACCESS.2016.2535486"); - assertEquals(Optional.of(URI.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=").toURL()), + assertEquals(Optional.of(URLUtil.create("https://ieeexplore.ieee.org/ielx7/6287639/7419931/07421926.pdf?tp=&arnumber=7421926&isnumber=7419931&ref=")), fetcher.findFullText(entry)); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/JstorFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/JstorFetcherTest.java index 283dc2cdf41..340f07f187a 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/JstorFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/JstorFetcherTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fetcher; -import java.net.URI; import java.net.URL; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @@ -10,6 +9,7 @@ import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.SearchBasedFetcher; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; @@ -80,7 +80,7 @@ void searchByUrlUsingId() throws Exception { @Test void fetchPDF() throws Exception { Optional url = fetcher.findFullText(bibEntry); - assertEquals(Optional.of(URI.create("https://www.jstor.org/stable/pdf/90002164.pdf").toURL()), url); + assertEquals(Optional.of(URLUtil.create("https://www.jstor.org/stable/pdf/90002164.pdf")), url); } @Override diff --git a/src/test/java/org/jabref/logic/importer/fetcher/OpenAccessDoiTest.java b/src/test/java/org/jabref/logic/importer/fetcher/OpenAccessDoiTest.java index dfaf7a99ffe..befec3a4c65 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/OpenAccessDoiTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/OpenAccessDoiTest.java @@ -1,9 +1,9 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.util.Optional; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.testutils.category.FetcherTest; @@ -28,7 +28,7 @@ void setUp() { @Test void findByDOI() throws IOException { entry.setField(StandardField.DOI, "10.1186/s12993-024-00248-9"); - assertEquals(Optional.of(URI.create("https://behavioralandbrainfunctions.biomedcentral.com/counter/pdf/10.1186/s12993-024-00248-9").toURL()), finder.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create("https://behavioralandbrainfunctions.biomedcentral.com/counter/pdf/10.1186/s12993-024-00248-9")), finder.findFullText(entry)); } @Test diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java index 46db0d3b191..265dd46ea61 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ResearchGateTest.java @@ -1,12 +1,12 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.util.List; import java.util.Optional; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.ImportFormatPreferences; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; @@ -45,7 +45,7 @@ void setUp() { @Test @DisabledOnCIServer("CI server is unreliable") void fullTextFoundByDOI() throws IOException, FetcherException { - assertEquals(Optional.of(URI.create(URL_PDF).toURL()), fetcher.findFullText(entry)); + assertEquals(Optional.of(URLUtil.create(URL_PDF)), fetcher.findFullText(entry)); } @Test diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java index f516a5d458d..2568fd27204 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java @@ -1,12 +1,12 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.util.Optional; import javafx.collections.FXCollections; import org.jabref.logic.importer.ImporterPreferences; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.support.DisabledOnCIServer; @@ -39,7 +39,7 @@ void findByDoiOldPage() throws IOException { entry.setField(StandardField.DOI, "10.1016/j.jrmge.2015.08.004"); assertEquals( - Optional.of(URI.create("https://www.sciencedirect.com/science/article/pii/S1674775515001079/pdfft?md5=2b19b19a387cffbae237ca6a987279df&pid=1-s2.0-S1674775515001079-main.pdf").toURL()), + Optional.of(URLUtil.create("https://www.sciencedirect.com/science/article/pii/S1674775515001079/pdfft?md5=2b19b19a387cffbae237ca6a987279df&pid=1-s2.0-S1674775515001079-main.pdf")), finder.findFullText(entry) ); } @@ -50,7 +50,7 @@ void findByDoiNewPage() throws IOException { entry.setField(StandardField.DOI, "10.1016/j.aasri.2014.09.002"); assertEquals( - Optional.of(URI.create("https://www.sciencedirect.com/science/article/pii/S2212671614001024/pdf?md5=4e2e9a369b4d5b3db5100aba599bef8b&pid=1-s2.0-S2212671614001024-main.pdf").toURL()), + Optional.of(URLUtil.create("https://www.sciencedirect.com/science/article/pii/S2212671614001024/pdf?md5=4e2e9a369b4d5b3db5100aba599bef8b&pid=1-s2.0-S2212671614001024-main.pdf")), finder.findFullText(entry) ); } @@ -62,7 +62,7 @@ void findByDoiWorksForBoneArticle() throws IOException { entry.setField(StandardField.DOI, "https://doi.org/10.1016/j.bone.2020.115226"); assertEquals( - Optional.of(URI.create("https://www.sciencedirect.com/science/article/pii/S8756328220300065/pdfft?md5=0ad75ff155637dec358e5c9fb8b90afd&pid=1-s2.0-S8756328220300065-main.pdf").toURL()), + Optional.of(URLUtil.create("https://www.sciencedirect.com/science/article/pii/S8756328220300065/pdfft?md5=0ad75ff155637dec358e5c9fb8b90afd&pid=1-s2.0-S8756328220300065-main.pdf")), finder.findFullText(entry) ); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/SpringerLinkTest.java b/src/test/java/org/jabref/logic/importer/fetcher/SpringerLinkTest.java index 116afd1791d..f5958ea8d95 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/SpringerLinkTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/SpringerLinkTest.java @@ -1,12 +1,12 @@ package org.jabref.logic.importer.fetcher; import java.io.IOException; -import java.net.URI; import java.util.Optional; import javafx.collections.FXCollections; import org.jabref.logic.importer.ImporterPreferences; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.support.DisabledOnCIServer; @@ -49,7 +49,7 @@ void doiNotPresent() throws IOException { void findByDOI() throws IOException { entry.setField(StandardField.DOI, "10.1186/s13677-015-0042-8"); assertEquals( - Optional.of(URI.create("http://link.springer.com/content/pdf/10.1186/s13677-015-0042-8.pdf").toURL()), + Optional.of(URLUtil.create("http://link.springer.com/content/pdf/10.1186/s13677-015-0042-8.pdf")), finder.findFullText(entry)); } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java index de6f276a015..318cb858508 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java @@ -140,6 +140,7 @@ void pdfTitleExtraction(String expectedTitle, String filePath) throws Exception private static Stream providePdfData() { return Stream.of( Arguments.of("Fundamentals of Distributed Computing: A Practical Tour of Vector Clock Systems", "/pdfs/PdfContentImporter/Baldoni2002.pdf"), + Arguments.of("JabRef Example for Reference Parsing", "/pdfs/IEEE/ieee-paper-cover.pdf"), Arguments.of("On How We Can Teach – Exploring New Ways in Professional Software Development for Students", "/pdfs/PdfContentImporter/Kriha2018.pdf"), Arguments.of("JabRef Example for Reference Parsing", "/pdfs/IEEE/ieee-paper.pdf"), Arguments.of("Paper Title", "/org/jabref/logic/importer/util/LNCS-minimal.pdf"), diff --git a/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java b/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java index 7de789227fe..badf10ac168 100644 --- a/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java +++ b/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java @@ -1,12 +1,12 @@ package org.jabref.logic.importer.util; -import java.net.URI; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Stream; +import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.LinkedFile; import org.junit.jupiter.params.ParameterizedTest; @@ -65,7 +65,7 @@ private static Stream stringsToParseTest() throws Exception { // parseCorrectOnlineInput Arguments.of( - Collections.singletonList(new LinkedFile(URI.create("http://arxiv.org/pdf/2010.08497v1").toURL(), "PDF")), + Collections.singletonList(new LinkedFile(URLUtil.create("http://arxiv.org/pdf/2010.08497v1"), "PDF")), ":http\\://arxiv.org/pdf/2010.08497v1:PDF" ), @@ -164,24 +164,24 @@ private static Stream stringsToParseTest() throws Exception { // url Arguments.of( - Collections.singletonList(new LinkedFile(URI.create("https://books.google.de/").toURL(), "")), + Collections.singletonList(new LinkedFile(URLUtil.create("https://books.google.de/"), "")), "https://books.google.de/" ), // url with www Arguments.of( - Collections.singletonList(new LinkedFile(URI.create("https://www.google.de/").toURL(), "")), + Collections.singletonList(new LinkedFile(URLUtil.create("https://www.google.de/"), "")), "https://www.google.de/" ), // url as file Arguments.of( - Collections.singletonList(new LinkedFile("", URI.create("http://ceur-ws.org/Vol-438").toURL(), "URL")), + Collections.singletonList(new LinkedFile("", URLUtil.create("http://ceur-ws.org/Vol-438"), "URL")), ":http\\://ceur-ws.org/Vol-438:URL" ), // url as file with desc Arguments.of( - Collections.singletonList(new LinkedFile("desc", URI.create("http://ceur-ws.org/Vol-438").toURL(), "URL")), + Collections.singletonList(new LinkedFile("desc", URLUtil.create("http://ceur-ws.org/Vol-438"), "URL")), "desc:http\\://ceur-ws.org/Vol-438:URL" ), // link with source url diff --git a/src/test/java/org/jabref/logic/net/URLDownloadTest.java b/src/test/java/org/jabref/logic/net/URLDownloadTest.java index ac5af134e71..734820a94fe 100644 --- a/src/test/java/org/jabref/logic/net/URLDownloadTest.java +++ b/src/test/java/org/jabref/logic/net/URLDownloadTest.java @@ -2,13 +2,13 @@ import java.io.File; import java.net.MalformedURLException; -import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import org.jabref.logic.importer.FetcherClientException; import org.jabref.logic.importer.FetcherServerException; +import org.jabref.logic.util.URLUtil; import org.jabref.support.DisabledOnCIServer; import org.jabref.testutils.category.FetcherTest; @@ -36,14 +36,14 @@ class URLDownloadTest { @Test void stringDownloadWithSetEncoding() throws Exception { - URLDownload dl = new URLDownload(URI.create("http://www.google.com").toURL()); + URLDownload dl = new URLDownload(URLUtil.create("http://www.google.com")); assertTrue(dl.asString().contains("Google"), "google.com should contain google"); } @Test void stringDownload() throws Exception { - URLDownload dl = new URLDownload(URI.create("http://www.google.com").toURL()); + URLDownload dl = new URLDownload(URLUtil.create("http://www.google.com")); assertTrue(dl.asString(StandardCharsets.UTF_8).contains("Google"), "google.com should contain google"); } @@ -52,7 +52,7 @@ void stringDownload() throws Exception { void fileDownload() throws Exception { File destination = File.createTempFile("jabref-test", ".html"); try { - URLDownload dl = new URLDownload(URI.create("http://www.google.com").toURL()); + URLDownload dl = new URLDownload(URLUtil.create("http://www.google.com")); dl.toFile(destination.toPath()); assertTrue(destination.exists(), "file must exist"); } finally { @@ -65,14 +65,14 @@ void fileDownload() throws Exception { @Test void determineMimeType() throws Exception { - URLDownload dl = new URLDownload(URI.create("http://www.google.com").toURL()); + URLDownload dl = new URLDownload(URLUtil.create("http://www.google.com")); assertTrue(dl.getMimeType().get().startsWith("text/html")); } @Test void downloadToTemporaryFilePathWithoutFileSavesAsTmpFile() throws Exception { - URLDownload google = new URLDownload(URI.create("http://www.google.com").toURL()); + URLDownload google = new URLDownload(URLUtil.create("http://www.google.com")); String path = google.toTemporaryFile().toString(); assertTrue(path.endsWith(".tmp"), path); @@ -80,7 +80,7 @@ void downloadToTemporaryFilePathWithoutFileSavesAsTmpFile() throws Exception { @Test void downloadToTemporaryFileKeepsName() throws Exception { - URLDownload google = new URLDownload(URI.create("https://github.com/JabRef/jabref/blob/main/LICENSE").toURL()); + URLDownload google = new URLDownload(URLUtil.create("https://github.com/JabRef/jabref/blob/main/LICENSE")); String path = google.toTemporaryFile().toString(); assertTrue(path.contains("LICENSE"), path); @@ -89,7 +89,7 @@ void downloadToTemporaryFileKeepsName() throws Exception { @Test @DisabledOnCIServer("CI Server is apparently blocked") void downloadOfFTPSucceeds() throws Exception { - URLDownload ftp = new URLDownload(URI.create("ftp://ftp.informatik.uni-stuttgart.de/pub/library/ncstrl.ustuttgart_fi/INPROC-2016-15/INPROC-2016-15.pdf").toURL()); + URLDownload ftp = new URLDownload(URLUtil.create("ftp://ftp.informatik.uni-stuttgart.de/pub/library/ncstrl.ustuttgart_fi/INPROC-2016-15/INPROC-2016-15.pdf")); Path path = ftp.toTemporaryFile(); assertNotNull(path); @@ -97,7 +97,7 @@ void downloadOfFTPSucceeds() throws Exception { @Test void downloadOfHttpSucceeds() throws Exception { - URLDownload ftp = new URLDownload(URI.create("http://www.jabref.org").toURL()); + URLDownload ftp = new URLDownload(URLUtil.create("http://www.jabref.org")); Path path = ftp.toTemporaryFile(); assertNotNull(path); @@ -105,7 +105,7 @@ void downloadOfHttpSucceeds() throws Exception { @Test void downloadOfHttpsSucceeds() throws Exception { - URLDownload ftp = new URLDownload(URI.create("https://www.jabref.org").toURL()); + URLDownload ftp = new URLDownload(URLUtil.create("https://www.jabref.org")); Path path = ftp.toTemporaryFile(); assertNotNull(path); @@ -113,21 +113,21 @@ void downloadOfHttpsSucceeds() throws Exception { @Test void checkConnectionSuccess() throws MalformedURLException { - URLDownload google = new URLDownload(URI.create("http://www.google.com").toURL()); + URLDownload google = new URLDownload(URLUtil.create("http://www.google.com")); assertTrue(google.canBeReached()); } @Test void checkConnectionFail() throws MalformedURLException { - URLDownload nonsense = new URLDownload(URI.create("http://nonsenseadddress").toURL()); + URLDownload nonsense = new URLDownload(URLUtil.create("http://nonsenseadddress")); assertThrows(UnirestException.class, nonsense::canBeReached); } @Test void connectTimeoutIsNeverNull() throws MalformedURLException { - URLDownload urlDownload = new URLDownload(URI.create("http://www.example.com").toURL()); + URLDownload urlDownload = new URLDownload(URLUtil.create("http://www.example.com")); assertNotNull(urlDownload.getConnectTimeout(), "there's a non-null default by the constructor"); urlDownload.setConnectTimeout(null); @@ -136,13 +136,13 @@ void connectTimeoutIsNeverNull() throws MalformedURLException { @Test void test503ErrorThrowsFetcherServerException() throws Exception { - URLDownload urlDownload = new URLDownload(URI.create("http://httpstat.us/503").toURL()); + URLDownload urlDownload = new URLDownload(URLUtil.create("http://httpstat.us/503")); assertThrows(FetcherServerException.class, urlDownload::asString); } @Test void test429ErrorThrowsFetcherClientException() throws Exception { - URLDownload urlDownload = new URLDownload(URI.create("http://httpstat.us/429").toURL()); + URLDownload urlDownload = new URLDownload(URLUtil.create("http://httpstat.us/429")); assertThrows(FetcherClientException.class, urlDownload::asString); } @@ -162,7 +162,7 @@ void redirectWorks(@TempDir Path tempDir) throws Exception { .withHeader("Content-Type", "application/pdf") .withBody(pdfContent))); - URLDownload urlDownload = new URLDownload(URI.create("http://localhost:2222/redirect").toURL()); + URLDownload urlDownload = new URLDownload(URLUtil.create("http://localhost:2222/redirect")); Path downloadedFile = tempDir.resolve("download.pdf"); urlDownload.toFile(downloadedFile); byte[] actual = Files.readAllBytes(downloadedFile); diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index d69d7a1df7e..7de7b641fc5 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -1,6 +1,8 @@ package org.jabref.logic.net; -import org.jabref.gui.fieldeditors.URLUtil; +import java.net.URI; + +import org.jabref.logic.util.URLUtil; import org.junit.jupiter.api.Test; @@ -78,4 +80,11 @@ void isURLshouldRejectInvalidURL() { void isURLshouldRejectEmbeddedURL() { assertFalse(URLUtil.isURL("dblp computer science bibliography, http://dblp.org")); } + + @Test + void createUriShouldHandlePipeCharacter() { + String input = "http://example.com/test|file"; + URI uri = URLUtil.createUri(input); + assertEquals("http://example.com/test%7Cfile", uri.toString()); + } } diff --git a/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java b/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java index 57e054027fa..69df8bb42f1 100644 --- a/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java +++ b/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java @@ -159,114 +159,94 @@ static Stream ooHTMLTransformFromRawBibliography() { // Non-numeric, parentheses, commas, full stops, slashes, hyphens, colons, italics Arguments.of( - " Smith, B., Jones, B., & Williams, J. (2016). Title of the test entry. BibTeX Journal, 34(3), 45–67. https://doi.org/10.1001/bla.blubb\n", + " Smith, B., Jones, B., & Williams, J. (2016). Title of the test entry. BibTeX Journal, 34(3), 45–67. https://doi.org/10.1001/bla.blubb

", STYLE_LIST.stream().filter(e -> "American Psychological Association 7th edition".equals(e.getTitle())).findAny().get() ), // Numeric type "[1]", brackets, newlines Arguments.of( - " \n" + - " [1] B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016, doi: 10.1001/bla.blubb.\n" + - " \n", + " [1] B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016, doi: 10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "IEEE".equals(e.getTitle())).findAny().get() ), // Numeric type "1." Arguments.of( - " \n" + - " 1. Smith, B., Jones, B., Williams, J.: Title of the test entry. BibTeX Journal. 34, 45–67 (2016). https://doi.org/10.1001/bla.blubb.\n" + - " \n", + " 1. Smith, B., Jones, B., Williams, J.: Title of the test entry. BibTeX Journal. 34, 45–67 (2016). https://doi.org/10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "Springer - Lecture Notes in Computer Science".equals(e.getTitle())).findAny().get() ), Arguments.of( - " Smith, Bill, Bob Jones, and Jeff Williams. 2016. “Title of the Test Entry.” Edited by Phil Taylor. BibTeX Journal 34 (3): 45–67. https://doi.org/10.1001/bla.blubb.\n", + " Smith, Bill, Bob Jones, and Jeff Williams. 2016. “Title of the Test Entry.” Edited by Phil Taylor. BibTeX Journal 34 (3): 45–67. https://doi.org/10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "Chicago Manual of Style 17th edition (author-date)".equals(e.getTitle())).findAny().get() ), // Semicolons Arguments.of( - " \n" + - " 1. Smith B, Jones B, Williams J. Title of the test entry. Taylor P, editor. BibTeX Journal [Internet]. 2016 Jul;34(3):45–67. Available from: https://github.com/JabRef\n" + - " \n", + " 1. Smith B, Jones B, Williams J. Title of the test entry. Taylor P, editor. BibTeX Journal [Internet]. 2016 Jul;34(3):45–67. Available from: https://github.com/JabRef

", STYLE_LIST.stream().filter(e -> "Vancouver".equals(e.getTitle())).findAny().get() ), Arguments.of( - " \n" + - " 1. Smith, B., Jones, B. & Williams, J. Title of the test entry. BibTeX Journal 34, 45–67 (2016).\n" + - " \n", + " 1. Smith, B., Jones, B. & Williams, J. Title of the test entry. BibTeX Journal 34, 45–67 (2016).

", STYLE_LIST.stream().filter(e -> "Nature".equals(e.getTitle())).findAny().get() ), Arguments.of( - " \n" + - " 1. Smith B, Jones B, Williams J. Title of the test entry. Taylor P, ed. BibTeX Journal. 2016;34(3):45-67. doi:10.1001/bla.blubb\n" + - " \n", + " 1. Smith B, Jones B, Williams J. Title of the test entry. Taylor P, ed. BibTeX Journal. 2016;34(3):45-67. doi:10.1001/bla.blubb

", STYLE_LIST.stream().filter(e -> "American Medical Association 11th edition".equals(e.getTitle())).findAny().get() ), // Small-caps Arguments.of( - " Smith, B., Jones, B., Williams, J. (2016) Title of the test entry Taylor, P. (ed.). BibTeX Journal, 34(3), pp. 45–67.\n", + " Smith, B., Jones, B., Williams, J. (2016) Title of the test entry Taylor, P. (ed.). BibTeX Journal, 34(3), pp. 45–67.

", STYLE_LIST.stream().filter(e -> "De Montfort University - Harvard".equals(e.getTitle())).findAny().get() ), // Underlines Arguments.of( - " Smith, Bill, Bob Jones, and Jeff Williams. “Title of the test entry.” Ed. Phil Taylor. BibTeX Journal 34.3 (2016): 45–67. .\n", + " Smith, Bill, Bob Jones, and Jeff Williams. “Title of the test entry.” Ed. Phil Taylor. BibTeX Journal 34.3 (2016): 45–67. .

", STYLE_LIST.stream().filter(e -> "Modern Language Association 7th edition (underline)".equals(e.getTitle())).findAny().get() ), // Non-breaking spaces Arguments.of( - " Smith, Bill, Bob Jones, & Jeff Williams, “Title of the test entry,” BibTeX Journal, 2016, vol. 34, no. 3, pp. 45–67.\n", + " Smith, Bill, Bob Jones, & Jeff Williams, “Title of the test entry,” BibTeX Journal, 2016, vol. 34, no. 3, pp. 45–67.

", STYLE_LIST.stream().filter(e -> "Histoire & Mesure (Français)".equals(e.getTitle())).findAny().get() ), // Numeric with a full stop - "1." Arguments.of( - " \n" + - " 1. Smith, B., Jones, B. and Williams, J. 2016. Title of the test entry. BibTeX Journal. 34: 45–67.\n" + - " \n", + " 1. Smith, B., Jones, B. and Williams, J. 2016. Title of the test entry. BibTeX Journal. 34: 45–67.

", STYLE_LIST.stream().filter(e -> "The Journal of Veterinary Medical Science".equals(e.getTitle())).findAny().get() ), // Bold text, bold numeric with a full stop - "1." Arguments.of( - " \n" + - " 1. Smith B, Jones B, Williams J. Title of the test entry. BibTeX Journal 2016 ; 34 : 45–67.\n" + - " \n", + " 1. Smith B, Jones B, Williams J. Title of the test entry. BibTeX Journal 2016 ; 34 : 45–67.

", STYLE_LIST.stream().filter(e -> "Acta Orthopædica Belgica".equals(e.getTitle())).findAny().get() ), // Naked numeric - "1" Arguments.of( - " \n" + - " 1 Smith Bill, Jones Bob, Williams Jeff. Title of the test entry. BibTeX Journal 2016;34(3):45–67. Doi: 10.1001/bla.blubb.\n" + - " \n", + " 1 Smith Bill, Jones Bob, Williams Jeff. Title of the test entry. BibTeX Journal 2016;34(3):45–67. Doi: 10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "Acta Anaesthesiologica Taiwanica".equals(e.getTitle())).findAny().get() ), // Numeric in parentheses - "(1)" Arguments.of( - " \n" + - " (1) Smith, B.; Jones, B.; Williams, J. Title of the Test Entry. BibTeX Journal 2016, 34 (3), 45–67. https://doi.org/10.1001/bla.blubb.\n" + - " \n", + " (1) Smith, B.; Jones, B.; Williams, J. Title of the Test Entry. BibTeX Journal 2016, 34 (3), 45–67. https://doi.org/10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "American Chemical Society".equals(e.getTitle())).findAny().get() ), // Numeric with right parenthesis - "1)" Arguments.of( - " \n" + - " 1) Smith B., Jones B., Williams J., BibTeX Journal, 34, 45–67 (2016).\n" + - " \n", + " 1) Smith B., Jones B., Williams J., BibTeX Journal, 34, 45–67 (2016).

", STYLE_LIST.stream().filter(e -> "Chemical and Pharmaceutical Bulletin".equals(e.getTitle())).findAny().get() ), // Numeric in superscript - "1" Arguments.of( - " 1 B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal 34(3), 45–67 (2016).\n", + " 1 B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal 34(3), 45–67 (2016).

", STYLE_LIST.stream().filter(e -> "American Institute of Physics 4th edition".equals(e.getTitle())).findAny().get() ) ); @@ -521,55 +501,43 @@ static Stream updateSingleNumericCitation() { // Type: "[1]" Arguments.of( - " \n" + - " [3] B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016, doi: 10.1001/bla.blubb.\n" + - " \n", + " [3] B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016, doi: 10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "IEEE".equals(e.getTitle())).findAny().get() ), // Type: "1." Arguments.of( - " \n" + - " 3. Smith, B., Jones, B. and Williams, J. 2016. Title of the test entry. BibTeX Journal. 34: 45–67.\n" + - " \n", + " 3. Smith, B., Jones, B. and Williams, J. 2016. Title of the test entry. BibTeX Journal. 34: 45–67.

", STYLE_LIST.stream().filter(e -> "The Journal of Veterinary Medical Science".equals(e.getTitle())).findAny().get() ), - // Type:"1." + // Type: "1." Arguments.of( - " \n" + - " 3. Smith B, Jones B, Williams J. Title of the test entry. BibTeX Journal 2016 ; 34 : 45–67.\n" + - " \n", + " 3. Smith B, Jones B, Williams J. Title of the test entry. BibTeX Journal 2016 ; 34 : 45–67.

", STYLE_LIST.stream().filter(e -> "Acta Orthopædica Belgica".equals(e.getTitle())).findAny().get() ), // Type: "1" Arguments.of( - " \n" + - " 3 Smith Bill, Jones Bob, Williams Jeff. Title of the test entry. BibTeX Journal 2016;34(3):45–67. Doi: 10.1001/bla.blubb.\n" + - " \n", + " 3 Smith Bill, Jones Bob, Williams Jeff. Title of the test entry. BibTeX Journal 2016;34(3):45–67. Doi: 10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "Acta Anaesthesiologica Taiwanica".equals(e.getTitle())).findAny().get() ), // Type: "(1)" Arguments.of( - " \n" + - " (3) Smith, B.; Jones, B.; Williams, J. Title of the Test Entry. BibTeX Journal 2016, 34 (3), 45–67. https://doi.org/10.1001/bla.blubb.\n" + - " \n", + " (3) Smith, B.; Jones, B.; Williams, J. Title of the Test Entry. BibTeX Journal 2016, 34 (3), 45–67. https://doi.org/10.1001/bla.blubb.

", STYLE_LIST.stream().filter(e -> "American Chemical Society".equals(e.getTitle())).findAny().get() ), // Type: "1)" Arguments.of( - " \n" + - " 3) Smith B., Jones B., Williams J., BibTeX Journal, 34, 45–67 (2016).\n" + - " \n", + " 3) Smith B., Jones B., Williams J., BibTeX Journal, 34, 45–67 (2016).

", STYLE_LIST.stream().filter(e -> "Chemical and Pharmaceutical Bulletin".equals(e.getTitle())).findAny().get() ), // Type: "1" Arguments.of( - " 3 B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal 34(3), 45–67 (2016).\n", + " 3 B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal 34(3), 45–67 (2016).

", STYLE_LIST.stream().filter(e -> "American Institute of Physics 4th edition".equals(e.getTitle())).findAny().get() ) ); diff --git a/src/test/java/org/jabref/logic/util/ExternalLinkCreatorTest.java b/src/test/java/org/jabref/logic/util/ExternalLinkCreatorTest.java index 28f1337b3e7..907dbe1504b 100644 --- a/src/test/java/org/jabref/logic/util/ExternalLinkCreatorTest.java +++ b/src/test/java/org/jabref/logic/util/ExternalLinkCreatorTest.java @@ -1,8 +1,6 @@ package org.jabref.logic.util; import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; import java.util.Optional; import org.jabref.model.entry.BibEntry; @@ -22,9 +20,9 @@ class ExternalLinkCreatorTest { private boolean urlIsValid(String url) { try { // This will throw on non-compliance to RFC2396. - URI.create(url).toURL().toURI(); + URLUtil.create(url); return true; - } catch (MalformedURLException | URISyntaxException e) { + } catch (MalformedURLException e) { return false; } } diff --git a/src/test/java/org/jabref/model/entry/BibEntryTest.java b/src/test/java/org/jabref/model/entry/BibEntryTest.java index 3d87ba15c48..a9910037379 100644 --- a/src/test/java/org/jabref/model/entry/BibEntryTest.java +++ b/src/test/java/org/jabref/model/entry/BibEntryTest.java @@ -1,6 +1,5 @@ package org.jabref.model.entry; -import java.net.URI; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -11,6 +10,7 @@ import java.util.Set; import java.util.stream.Stream; +import org.jabref.logic.util.URLUtil; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.field.BibField; @@ -259,7 +259,7 @@ void getAndAddToLinkedFileList() { void replaceOfLinkWorks() throws Exception { List files = new ArrayList<>(); String urlAsString = "https://www.example.org/file.pdf"; - files.add(new LinkedFile(URI.create(urlAsString).toURL(), "")); + files.add(new LinkedFile(URLUtil.create(urlAsString), "")); entry.setFiles(files); LinkedFile linkedFile = new LinkedFile("", Path.of("file.pdf", ""), ""); diff --git a/src/test/java/org/jabref/model/entry/identifier/SSRNTest.java b/src/test/java/org/jabref/model/entry/identifier/SSRNTest.java index c9a9d9fad66..62f5e2a5bd6 100644 --- a/src/test/java/org/jabref/model/entry/identifier/SSRNTest.java +++ b/src/test/java/org/jabref/model/entry/identifier/SSRNTest.java @@ -4,6 +4,8 @@ import java.util.Optional; import java.util.stream.Stream; +import org.jabref.logic.util.URLUtil; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -61,7 +63,7 @@ public void identifierNormalisation() { @Test public void identifierExternalUrl() { SSRN ssrnIdentifier = new SSRN(123456); - URI uri = URI.create("https://ssrn.com/abstract=123456"); + URI uri = URLUtil.createUri("https://ssrn.com/abstract=123456"); assertEquals(Optional.of(uri), ssrnIdentifier.getExternalURI()); } } diff --git a/src/test/resources/pdfs/IEEE/ieee-paper-cover.pdf b/src/test/resources/pdfs/IEEE/ieee-paper-cover.pdf new file mode 100644 index 00000000000..4c1ca1ebde2 Binary files /dev/null and b/src/test/resources/pdfs/IEEE/ieee-paper-cover.pdf differ