diff --git a/.github/ghprcomment.yml b/.github/ghprcomment.yml index 7e5f9de7092..c1dccfa756d 100644 --- a/.github/ghprcomment.yml +++ b/.github/ghprcomment.yml @@ -54,6 +54,18 @@ Please carefully follow [the setup guide for the codestyle](https://devdocs.jabref.org/getting-into-the-code/guidelines-for-setting-up-a-local-workspace/intellij-13-code-style.html). Afterwards, please [run checkstyle locally](https://devdocs.jabref.org/getting-into-the-code/guidelines-for-setting-up-a-local-workspace/intellij-13-code-style.html#run-checkstyle) and fix the issues, commit, and push. +- jobName: prettier + workflowName: 'Source Code Tests' + message: > + Your code currently does not meet JabRef's code guidelines. + We use [prettier-java](https://www.jhipster.tech/prettier-java/) to ensure "modern" Java coding practices. + You can see which checks are failing by locating the box "Some checks were not successful" on the pull request page. + To see the test output, locate "Source Code Tests / prettier (pull_request)" and click on it. + + + The issues found can be **automatically fixed**. + Please execute `npx prettier --write "**/*.java"` on the command line check the results, commit, and push. + Alternativly, you can execute the workflow "Fix prettier" manually using GitHub actions. - jobName: OpenRewrite workflowName: 'Source Code Tests' message: > diff --git a/.github/workflows/fix-prettier.yml b/.github/workflows/fix-prettier.yml new file mode 100644 index 00000000000..51097c69fad --- /dev/null +++ b/.github/workflows/fix-prettier.yml @@ -0,0 +1,41 @@ +name: Fix prettier + +on: + push: + workflow_dispatch: + +concurrency: + group: "${{ github.workflow }}-${{ github.head_ref || github.ref }}" + cancel-in-progress: true + +permissions: + contents: write + pull-requests: read + +jobs: + prettier: + # enable manual run - and automatic fix in the JabRef organization + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.repository_owner == 'JabRef') + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + persist-credentials: false + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: 'latest' + cache: 'npm' + + - run: npm ci + + - run: npx prettier --write "**/*.java" + + - name: Commit & Push changes + uses: actions-js/push@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + message: "Formatted using pretter-java" diff --git a/.github/workflows/tests-code.yml b/.github/workflows/tests-code.yml index 0b43ffb33b3..4fa803afa70 100644 --- a/.github/workflows/tests-code.yml +++ b/.github/workflows/tests-code.yml @@ -78,6 +78,22 @@ jobs: - name: Run checkstyle using gradle run: ./gradlew checkstyleMain checkstyleTest checkstyleJmh + prettier: + name: prettier + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v5 + + - uses: actions/setup-node@v4 + with: + node-version: 'latest' + cache: 'npm' + + - run: npm ci + + - run: npx prettier "**/*.java" --check + openrewrite: name: OpenRewrite runs-on: ubuntu-latest diff --git a/.jbang/CheckoutPR.java b/.jbang/CheckoutPR.java index 98801f5b4e8..a9534eff806 100644 --- a/.jbang/CheckoutPR.java +++ b/.jbang/CheckoutPR.java @@ -1,7 +1,6 @@ import java.io.File; import java.util.List; import java.util.Optional; - import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; @@ -24,12 +23,15 @@ //DEPS org.eclipse.jgit:org.eclipse.jgit.pgm:7.3.0.202506031305-r public class CheckoutPR { + public static void main(String[] args) throws Exception { GitHub github = new GitHubBuilder().build(); GHRepository repo = github.getRepository("JabRef/jabref"); if (args.length != 1) { - System.err.println("Usage: jbang CheckoutPR.java |"); + System.err.println( + "Usage: jbang CheckoutPR.java |" + ); System.exit(1); } @@ -43,7 +45,9 @@ public static void main(String[] args) throws Exception { GHPullRequest pr; if (prNumber == -1) { - System.out.println("Trying to find pull request with branch " + arg); + System.out.println( + "Trying to find pull request with branch " + arg + ); String[] parts = arg.split(":"); String contributor; String branchName; @@ -56,20 +60,34 @@ public static void main(String[] args) throws Exception { } // We need to query all pull requests to be able to handle closed and merged ones - PagedIterator prIterator = repo.queryPullRequests().direction(GHDirection.DESC).state(GHIssueState.ALL).list().iterator(); + PagedIterator prIterator = repo + .queryPullRequests() + .direction(GHDirection.DESC) + .state(GHIssueState.ALL) + .list() + .iterator(); boolean found = false; pr = null; while (prIterator.hasNext()) { pr = prIterator.next(); - if ((contributor.isEmpty() || pr.getHead().getUser().getLogin().equals(contributor)) && - pr.getHead().getRef().equals(branchName)) { + if ( + (contributor.isEmpty() + || pr + .getHead() + .getUser() + .getLogin() + .equals(contributor)) + && pr.getHead().getRef().equals(branchName) + ) { found = true; System.out.println("Found pull request #" + pr.getNumber()); break; } } if (!found) { - throw new IllegalArgumentException("Pull request not found for branch: " + branchName); + throw new IllegalArgumentException( + "Pull request not found for branch: " + branchName + ); } } else { pr = repo.getPullRequest(prNumber); @@ -78,28 +96,41 @@ public static void main(String[] args) throws Exception { System.out.println("Determined PR URL is " + pr.getUrl()); if (pr.isMerged()) { - System.out.println("Pull request is already merged - checking out main branch..."); + System.out.println( + "Pull request is already merged - checking out main branch..." + ); checkoutUpstreamMain(); return; } if (pr.getState().equals(GHIssueState.CLOSED)) { - System.out.println("Warning: Pull request is closed. Trying to continue nevertheless."); + System.out.println( + "Warning: Pull request is closed. Trying to continue nevertheless." + ); } String headRef = pr.getHead().getRef(); - String headRepoCloneUrl = pr.getHead().getRepository().getHttpTransportUrl(); + String headRepoCloneUrl = pr + .getHead() + .getRepository() + .getHttpTransportUrl(); final String remoteName = "tmp-remote"; - final String localBranchName = "pr--" + pr.getNumber() + "--" + pr.getUser().getLogin() + "--" + headRef; + final String localBranchName = + "pr--" + + pr.getNumber() + + "--" + + pr.getUser().getLogin() + + "--" + + headRef; // Open the repository in the current directory (".") File repoDir = new File("."); Repository repository = new FileRepositoryBuilder() - .setGitDir(new File(repoDir, ".git")) - .readEnvironment() - .findGitDir() - .build(); + .setGitDir(new File(repoDir, ".git")) + .readEnvironment() + .findGitDir() + .build(); try (Git git = new Git(repository)) { // If current branch is "tmp-branch", checkout "main" @@ -111,52 +142,70 @@ public static void main(String[] args) throws Exception { // Check if branch "tmp-branch" exists and remove it if present List branches = git.branchList().call(); - boolean branchExists = branches.stream().anyMatch(branch -> branch.getName().endsWith(localBranchName)); + boolean branchExists = branches + .stream() + .anyMatch(branch -> branch.getName().endsWith(localBranchName)); if (branchExists) { System.out.println("Deleting branch 'tmp-branch'"); - git.branchDelete().setBranchNames(localBranchName).setForce(true).call(); + git + .branchDelete() + .setBranchNames(localBranchName) + .setForce(true) + .call(); } // Check if the remote "tmp-remote" exists and remove it if present List remotes = git.remoteList().call(); - boolean remoteExists = remotes.stream().anyMatch(remote -> remote.getName().equals(remoteName)); + boolean remoteExists = remotes + .stream() + .anyMatch(remote -> remote.getName().equals(remoteName)); if (remoteExists) { System.out.println("Removing remote 'tmp-remote'"); git.remoteRemove().setRemoteName(remoteName).call(); } System.out.println("Adding remote 'tmp-remote'"); - git.remoteAdd() - .setName(remoteName) - .setUri(new URIish(headRepoCloneUrl)) - .call(); + git + .remoteAdd() + .setName(remoteName) + .setUri(new URIish(headRepoCloneUrl)) + .call(); } // Has nice output, therefore we use pgm System.out.println("Fetching..."); - String[] jGitArgsFetch = {"fetch", remoteName}; + String[] jGitArgsFetch = { "fetch", remoteName }; org.eclipse.jgit.pgm.Main.main(jGitArgsFetch); try (Git git = new Git(repository)) { System.out.println("Checking out..."); - git.checkout() - .setCreateBranch(true) - .setName(localBranchName) - .setStartPoint(remoteName + "/" + headRef) - .call(); + git + .checkout() + .setCreateBranch(true) + .setName(localBranchName) + .setStartPoint(remoteName + "/" + headRef) + .call(); } - System.out.println("Checked out PR #" + pr.getNumber() + " (" + pr.getTitle() + ") to branch " + localBranchName + "."); + System.out.println( + "Checked out PR #" + + pr.getNumber() + + " (" + + pr.getTitle() + + ") to branch " + + localBranchName + + "." + ); System.out.println("Checked out commit " + pr.getHead().getSha() + "."); } private static void checkoutUpstreamMain() throws Exception { File repoDir = new File("."); Repository repository = new FileRepositoryBuilder() - .setGitDir(new File(repoDir, ".git")) - .readEnvironment() - .findGitDir() - .build(); + .setGitDir(new File(repoDir, ".git")) + .readEnvironment() + .findGitDir() + .build(); try (Git git = new Git(repository)) { final String upstreamName = "upstream"; @@ -164,9 +213,17 @@ private static void checkoutUpstreamMain() throws Exception { // Check if a remote pointing to JabRef/jabref already exists List remotes = git.remoteList().call(); - Optional jabrefRemote = remotes.stream() + Optional jabrefRemote = remotes + .stream() // We use "contains", because there could be SSH remote URLs - .filter(r -> r.getURIs().stream().anyMatch(uri -> uri.toString().contains("JabRef/jabref"))) + .filter(r -> + r + .getURIs() + .stream() + .anyMatch(uri -> + uri.toString().contains("JabRef/jabref") + ) + ) .findFirst(); String remoteToUse; @@ -174,8 +231,11 @@ private static void checkoutUpstreamMain() throws Exception { remoteToUse = jabrefRemote.get().getName(); System.out.println("Using existing remote: " + remoteToUse); } else { - System.out.println("Adding remote 'upstream' pointing to " + jabrefRepoUrl); - git.remoteAdd() + System.out.println( + "Adding remote 'upstream' pointing to " + jabrefRepoUrl + ); + git + .remoteAdd() .setName(upstreamName) .setUri(new URIish(jabrefRepoUrl)) .call(); @@ -191,12 +251,12 @@ private static void checkoutUpstreamMain() throws Exception { // Fetch from the selected remote System.out.println("Fetching from " + remoteToUse); - String[] jGitArgsFetch = {"fetch", remoteToUse}; + String[] jGitArgsFetch = { "fetch", remoteToUse }; org.eclipse.jgit.pgm.Main.main(jGitArgsFetch); // Merge upstream/main System.out.println("Merging " + remoteToUse + "/main into main"); - String[] jGitArgsMerge = {"merge", remoteToUse + "/main"}; + String[] jGitArgsMerge = { "merge", remoteToUse + "/main" }; org.eclipse.jgit.pgm.Main.main(jGitArgsMerge); } } diff --git a/.jbang/CloneJabRef.java b/.jbang/CloneJabRef.java index 4b6fbb0e047..5a59c748f4a 100644 --- a/.jbang/CloneJabRef.java +++ b/.jbang/CloneJabRef.java @@ -9,6 +9,7 @@ //DEPS org.eclipse.jgit:org.eclipse.jgit.pgm:7.3.0.202506031305-r public class CloneJabRef { + public static void main(String[] args) throws Exception { Path targetDir; if (args.length == 1) { @@ -22,7 +23,12 @@ public static void main(String[] args) throws Exception { return; } - String[] jGitArgs = {"clone", "https://github.com/JabRef/jabref.git", "--recurse-submodules", targetDir.toString()}; + String[] jGitArgs = { + "clone", + "https://github.com/JabRef/jabref.git", + "--recurse-submodules", + targetDir.toString(), + }; org.eclipse.jgit.pgm.Main.main(jGitArgs); System.out.println("JabRef code available at: " + targetDir); diff --git a/.jbang/JabKitLauncher.java b/.jbang/JabKitLauncher.java index 0678a94b3dc..c754bb0626b 100644 --- a/.jbang/JabKitLauncher.java +++ b/.jbang/JabKitLauncher.java @@ -41,6 +41,7 @@ /// This class is required for [jbang](https://www.jbang.dev/) public class JabKitLauncher { + public static void main(String[] args) { org.jabref.JabKit.main(args); } diff --git a/.jbang/JabLsLauncher.java b/.jbang/JabLsLauncher.java index ea64b2320e7..140681aca0c 100644 --- a/.jbang/JabLsLauncher.java +++ b/.jbang/JabLsLauncher.java @@ -45,6 +45,7 @@ /// This class is required for [jbang](https://www.jbang.dev/) public class JabLsLauncher { + public static void main(String[] args) throws Exception { org.jabref.languageserver.cli.ServerCli.main(args); } diff --git a/.jbang/JabSrvLauncher.java b/.jbang/JabSrvLauncher.java index 353a8c75f97..1a78fb8fbc3 100644 --- a/.jbang/JabSrvLauncher.java +++ b/.jbang/JabSrvLauncher.java @@ -89,6 +89,7 @@ /// This class is required for [jbang](https://www.jbang.dev/) public class JabSrvLauncher { + public static void main(String[] args) throws Exception { org.jabref.http.server.cli.ServerCli.main(args); } diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 00000000000..c353a95662f --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,4 @@ +plugins: + - prettier-plugin-java +tabWidth: 4 +experimentalOperatorPosition: start diff --git a/.vscode/settings.json b/.vscode/settings.json index c7040d901f8..07049970277 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,4 +4,5 @@ "java.checkstyle.configuration": "${workspaceFolder}/config/checkstyle/checkstyle_reviewdog.xml", "java.checkstyle.version": "10.21.0", "java.compile.nullAnalysis.mode": "automatic" + "java.completion.importOrder": ["#"] } diff --git a/build-support/src/main/java/CitationStyleCatalogGenerator.java b/build-support/src/main/java/CitationStyleCatalogGenerator.java index 0f00c97314f..f008b553573 100644 --- a/build-support/src/main/java/CitationStyleCatalogGenerator.java +++ b/build-support/src/main/java/CitationStyleCatalogGenerator.java @@ -17,6 +17,7 @@ //SOURCES ../../../../jablib/src/main/java/org/jabref/logic/util/UnknownFileType.java //SOURCES ../../../../jablib/src/main/java/org/jabref/model/util/OptionalUtil.java +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -25,12 +26,9 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Stream; - import org.jabref.architecture.AllowedToUseClassGetResource; import org.jabref.logic.citationstyle.CSLStyleUtils; import org.jabref.logic.citationstyle.CitationStyle; - -import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,11 +39,17 @@ /// Has to be started in the root of the repository due to @AllowedToUseClassGetResource("Required for loading internal CSL styles") public class CitationStyleCatalogGenerator { - private static final Path STYLES_ROOT = Path.of("jablib/src/main/resources/csl-styles"); - private static final String CATALOG_PATH = "jablib/build/generated/resources/citation-style-catalog.json"; + + private static final Path STYLES_ROOT = Path.of( + "jablib/src/main/resources/csl-styles" + ); + private static final String CATALOG_PATH = + "jablib/build/generated/resources/citation-style-catalog.json"; private static final String DEFAULT_STYLE = "ieee.csl"; - private static final Logger LOGGER = LoggerFactory.getLogger(CitationStyleCatalogGenerator.class); + private static final Logger LOGGER = LoggerFactory.getLogger( + CitationStyleCatalogGenerator.class + ); public static void main(String[] args) { generateCitationStyleCatalog(); @@ -56,13 +60,21 @@ public static void generateCitationStyleCatalog() { // JBang's gradle plugin has a strange path handling. If "application->run" is started from the IDE, the path ends with "jabgui" Path root = Path.of(".").toAbsolutePath().normalize(); String rootFilename = root.getFileName().toString(); - if (!"jabref".equalsIgnoreCase(rootFilename) && rootFilename.startsWith("jab")) { + if ( + !"jabref".equalsIgnoreCase(rootFilename) + && rootFilename.startsWith("jab") + ) { LOGGER.info("Running from IDE, adjusting path to styles root"); root = root.getParent(); } Path stylesRoot = root.resolve(STYLES_ROOT); if (!Files.exists(stylesRoot.resolve(DEFAULT_STYLE))) { - LOGGER.error("Could not find any citation style. Tried with {}. Tried in {}. Current directory: {}", DEFAULT_STYLE, root, Path.of(".").toAbsolutePath()); + LOGGER.error( + "Could not find any citation style. Tried with {}. Tried in {}. Current directory: {}", + DEFAULT_STYLE, + root, + Path.of(".").toAbsolutePath() + ); return; } @@ -75,37 +87,56 @@ public static void generateCitationStyleCatalog() { } } - private static List discoverStyles(Path path) throws IOException { - try (Stream stream = Files.find(path, 1, (file, _) -> file.toString().endsWith("csl"))) { - return stream.map(Path::toAbsolutePath) - .map(Path::toString) - .map(CSLStyleUtils::createCitationStyleFromFile) - .flatMap(Optional::stream) - .toList(); + private static List discoverStyles(Path path) + throws IOException { + try ( + Stream stream = Files.find(path, 1, (file, _) -> + file.toString().endsWith("csl") + ) + ) { + return stream + .map(Path::toAbsolutePath) + .map(Path::toString) + .map(CSLStyleUtils::createCitationStyleFromFile) + .flatMap(Optional::stream) + .toList(); } } - private static void generateCatalog(List styles, Path stylesRoot, Path catalogPath) throws IOException { + private static void generateCatalog( + List styles, + Path stylesRoot, + Path catalogPath + ) throws IOException { // Create a JSON representation of the styles ObjectMapper mapper = new ObjectMapper(); - List> styleInfoList = styles.stream() - .map(style -> { - Map info = new HashMap<>(); - Path stylePath = Path.of(style.getFilePath()); - Path relativePath = stylesRoot.toAbsolutePath().relativize(stylePath.toAbsolutePath()); - info.put("path", relativePath.toString()); - info.put("title", style.getTitle()); - info.put("shortTitle", style.getShortTitle()); - info.put("isNumeric", style.isNumericStyle()); - info.put("hasBibliography", style.hasBibliography()); - info.put("usesHangingIndent", style.usesHangingIndent()); - return info; - }) - .toList(); - - String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(styleInfoList); + List> styleInfoList = styles + .stream() + .map(style -> { + Map info = new HashMap<>(); + Path stylePath = Path.of(style.getFilePath()); + Path relativePath = stylesRoot + .toAbsolutePath() + .relativize(stylePath.toAbsolutePath()); + info.put("path", relativePath.toString()); + info.put("title", style.getTitle()); + info.put("shortTitle", style.getShortTitle()); + info.put("isNumeric", style.isNumericStyle()); + info.put("hasBibliography", style.hasBibliography()); + info.put("usesHangingIndent", style.usesHangingIndent()); + return info; + }) + .toList(); + + String json = mapper + .writerWithDefaultPrettyPrinter() + .writeValueAsString(styleInfoList); Files.writeString(catalogPath, json); - LOGGER.info("Generated citation style catalog with {} styles at {}", styles.size(), catalogPath); + LOGGER.info( + "Generated citation style catalog with {} styles at {}", + styles.size(), + catalogPath + ); } } diff --git a/build-support/src/main/java/JournalListMvGenerator.java b/build-support/src/main/java/JournalListMvGenerator.java index cf945736b98..0ea111b055d 100644 --- a/build-support/src/main/java/JournalListMvGenerator.java +++ b/build-support/src/main/java/JournalListMvGenerator.java @@ -34,77 +34,114 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; - -import org.jabref.logic.journals.Abbreviation; -import org.jabref.logic.journals.JournalAbbreviationLoader; - import org.h2.mvstore.MVMap; import org.h2.mvstore.MVStore; +import org.jabref.logic.journals.Abbreviation; +import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jooq.lambda.Unchecked; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /// Has to be started in the root of the repository due to public class JournalListMvGenerator { - private static final Logger LOGGER = LoggerFactory.getLogger(JournalListMvGenerator.class); + private static final Logger LOGGER = LoggerFactory.getLogger( + JournalListMvGenerator.class + ); public static void main(String[] args) throws IOException { boolean verbose = (args.length == 1) && ("--verbose".equals(args[0])); - Path abbreviationsDirectory = Path.of("jablib", "src", "main", "abbrv.jabref.org", "journals"); + Path abbreviationsDirectory = Path.of( + "jablib", + "src", + "main", + "abbrv.jabref.org", + "journals" + ); if (!Files.exists(abbreviationsDirectory)) { - System.out.println("Path " + abbreviationsDirectory.toAbsolutePath() + " does not exist"); + System.out.println( + "Path " + + abbreviationsDirectory.toAbsolutePath() + + " does not exist" + ); System.exit(0); } // Directory layout aligns to other plugins (e.g., XJF plugin (https://github.com/bjornvester/xjc-gradle-plugin)) - Path journalListMvFile = Path.of("jablib", "build", "generated", "resources", "journals", "journal-list.mv"); + Path journalListMvFile = Path.of( + "jablib", + "build", + "generated", + "resources", + "journals", + "journal-list.mv" + ); Set ignoredNames = Set.of( - // remove all lists without dot in them: - // we use abbreviation lists containing dots in them only (to be consistent) - "journal_abbreviations_entrez.csv", - "journal_abbreviations_medicus.csv", - "journal_abbreviations_webofscience-dotless.csv", - - // we currently do not have good support for BibTeX strings - "journal_abbreviations_ieee_strings.csv" + // remove all lists without dot in them: + // we use abbreviation lists containing dots in them only (to be consistent) + "journal_abbreviations_entrez.csv", + "journal_abbreviations_medicus.csv", + "journal_abbreviations_webofscience-dotless.csv", + // we currently do not have good support for BibTeX strings + "journal_abbreviations_ieee_strings.csv" ); Files.createDirectories(journalListMvFile.getParent()); - try (DirectoryStream stream = Files.newDirectoryStream(abbreviationsDirectory, "*.csv"); - MVStore store = new MVStore.Builder(). - fileName(journalListMvFile.toString()). - compressHigh(). - open()) { - MVMap fullToAbbreviation = store.openMap("FullToAbbreviation"); - stream.forEach(Unchecked.consumer(path -> { - String fileName = path.getFileName().toString(); - System.out.print("Checking "); - System.out.print(fileName); - if (ignoredNames.contains(fileName)) { - System.out.println(" ignored"); - } else { - System.out.println("..."); - Collection abbreviations = JournalAbbreviationLoader.readAbbreviationsFromCsvFile(path); - Map abbreviationMap = abbreviations - .stream() - .collect(Collectors.toMap( - Abbreviation::getName, - abbreviation -> abbreviation, - (abbreviation1, abbreviation2) -> { - if (verbose) { - System.out.println("Double entry " + abbreviation1.getName()); + try ( + DirectoryStream stream = Files.newDirectoryStream( + abbreviationsDirectory, + "*.csv" + ); + MVStore store = new MVStore.Builder() + .fileName(journalListMvFile.toString()) + .compressHigh() + .open() + ) { + MVMap fullToAbbreviation = store.openMap( + "FullToAbbreviation" + ); + stream.forEach( + Unchecked.consumer(path -> { + String fileName = path.getFileName().toString(); + System.out.print("Checking "); + System.out.print(fileName); + if (ignoredNames.contains(fileName)) { + System.out.println(" ignored"); + } else { + System.out.println("..."); + Collection abbreviations = + JournalAbbreviationLoader.readAbbreviationsFromCsvFile( + path + ); + Map abbreviationMap = + abbreviations + .stream() + .collect( + Collectors.toMap( + Abbreviation::getName, + abbreviation -> abbreviation, + (abbreviation1, abbreviation2) -> { + if (verbose) { + System.out.println( + "Double entry " + + abbreviation1.getName() + ); + } + return abbreviation2; } - return abbreviation2; - })); - fullToAbbreviation.putAll(abbreviationMap); - } - })); + ) + ); + fullToAbbreviation.putAll(abbreviationMap); + } + }) + ); } - LOGGER.info("Generated journal list at {}", journalListMvFile.toAbsolutePath()); + LOGGER.info( + "Generated journal list at {}", + journalListMvFile.toAbsolutePath() + ); } } diff --git a/build-support/src/main/java/LtwaListMvGenerator.java b/build-support/src/main/java/LtwaListMvGenerator.java index 063d3405380..9732c1fbf00 100644 --- a/build-support/src/main/java/LtwaListMvGenerator.java +++ b/build-support/src/main/java/LtwaListMvGenerator.java @@ -29,14 +29,12 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; - +import org.h2.mvstore.MVMap; +import org.h2.mvstore.MVStore; import org.jabref.logic.journals.ltwa.LtwaEntry; import org.jabref.logic.journals.ltwa.LtwaTsvParser; import org.jabref.logic.journals.ltwa.NormalizeUtils; import org.jabref.logic.journals.ltwa.PrefixTree; - -import org.h2.mvstore.MVMap; -import org.h2.mvstore.MVStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,23 +43,42 @@ /// Has to be started in the root of the repository due to public class LtwaListMvGenerator { - private static final Logger LOGGER = LoggerFactory.getLogger(LtwaListMvGenerator.class); + private static final Logger LOGGER = LoggerFactory.getLogger( + LtwaListMvGenerator.class + ); public static void main(String[] args) { try { - Path tempCsvFile = Path.of("jablib", "build", "tmp", "ltwa_20210702.csv"); + Path tempCsvFile = Path.of( + "jablib", + "build", + "tmp", + "ltwa_20210702.csv" + ); if (!Files.exists(tempCsvFile)) { - LOGGER.error("LTWA CSV file not found at {}. Please execute gradle task downloadLtwaFile.", tempCsvFile); + LOGGER.error( + "LTWA CSV file not found at {}. Please execute gradle task downloadLtwaFile.", + tempCsvFile + ); return; } - Path outputDir = Path.of("jablib", "build", "generated", "resources", "journals"); + Path outputDir = Path.of( + "jablib", + "build", + "generated", + "resources", + "journals" + ); Files.createDirectories(outputDir); Path outputFile = outputDir.resolve("ltwa-list.mv"); generateMvStore(tempCsvFile, outputFile); - LOGGER.info("LTWA MVStore file generated successfully at {}.", outputFile.toAbsolutePath()); + LOGGER.info( + "LTWA MVStore file generated successfully at {}.", + outputFile.toAbsolutePath() + ); } catch (IOException e) { LOGGER.error("Error generating LTWA MVStore file.", e); } @@ -74,41 +91,63 @@ public static void main(String[] args) { * @param outputFile Path where the MVStore file will be written * @throws IOException If an I/O error occurs */ - private static void generateMvStore(Path inputFile, Path outputFile) throws IOException { + private static void generateMvStore(Path inputFile, Path outputFile) + throws IOException { LOGGER.info("Parsing LTWA file..."); LtwaTsvParser parser = new LtwaTsvParser(inputFile); List entries = parser.parse(); LOGGER.info("Found {} LTWA entries", entries.size()); - try (MVStore store = new MVStore.Builder() + try ( + MVStore store = new MVStore.Builder() .fileName(outputFile.toString()) .compressHigh() - .open()) { - MVMap> prefixMap = store.openMap("Prefixes"); - MVMap> suffixMap = store.openMap("Suffixes"); - String inflection = Character.toString(PrefixTree.WILD_CARD).repeat(3) + " "; + .open() + ) { + MVMap> prefixMap = store.openMap( + "Prefixes" + ); + MVMap> suffixMap = store.openMap( + "Suffixes" + ); + String inflection = + Character.toString(PrefixTree.WILD_CARD).repeat(3) + " "; entries.forEach(entry -> - NormalizeUtils.normalize(entry.word()) - .map(String::toLowerCase) - .map(word -> word.replace(" ", inflection)) - .ifPresent(word -> { - if (word.startsWith("-")) { - String key = word.substring(1); - suffixMap.computeIfAbsent(key, _ -> - Stream.builder().build().collect(Collectors.toList()) - ).add(entry); - } else { - String key = word.endsWith("-") ? word.substring(0, word.length() - 1) : word; - prefixMap.computeIfAbsent(key, _ -> - Stream.builder().build().collect(Collectors.toList()) - ).add(entry); - } - }) + NormalizeUtils.normalize(entry.word()) + .map(String::toLowerCase) + .map(word -> word.replace(" ", inflection)) + .ifPresent(word -> { + if (word.startsWith("-")) { + String key = word.substring(1); + suffixMap + .computeIfAbsent(key, _ -> + Stream.builder() + .build() + .collect(Collectors.toList()) + ) + .add(entry); + } else { + String key = word.endsWith("-") + ? word.substring(0, word.length() - 1) + : word; + prefixMap + .computeIfAbsent(key, _ -> + Stream.builder() + .build() + .collect(Collectors.toList()) + ) + .add(entry); + } + }) ); - LOGGER.info("Stored {} prefixes and {} suffixes", prefixMap.size(), suffixMap.size()); + LOGGER.info( + "Stored {} prefixes and {} suffixes", + prefixMap.size(), + suffixMap.size() + ); } } } diff --git a/build-support/src/test/java/CitationStyleCatalogGeneratorTest.java b/build-support/src/test/java/CitationStyleCatalogGeneratorTest.java index 39e422d27f5..642305b9130 100644 --- a/build-support/src/test/java/CitationStyleCatalogGeneratorTest.java +++ b/build-support/src/test/java/CitationStyleCatalogGeneratorTest.java @@ -1,24 +1,23 @@ // TODO: Integrate in JBang and tests.yml +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Map; - import org.jabref.generators.CitationStyleCatalogGenerator; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - class CitationStyleCatalogGeneratorTest { - private static final String CATALOG_PATH = "build/generated/resources/citation-style-catalog.json"; + private static final String CATALOG_PATH = + "build/generated/resources/citation-style-catalog.json"; @BeforeEach void generateCatalog() { @@ -29,24 +28,48 @@ void generateCatalog() { void catalogGenerationContainsEntries() throws IOException { Path catalogPath = Path.of(CATALOG_PATH); - assertTrue(Files.exists(catalogPath), "Catalog file should exist at " + CATALOG_PATH); + assertTrue( + Files.exists(catalogPath), + "Catalog file should exist at " + CATALOG_PATH + ); // Read and parse the catalog String catalogContent = Files.readString(catalogPath); ObjectMapper mapper = new ObjectMapper(); List> styles = mapper.readValue( - catalogContent, - new TypeReference<>() { - }); + catalogContent, + new TypeReference<>() {} + ); - assertFalse(styles.isEmpty(), "Catalog should contain at least one citation style"); + assertFalse( + styles.isEmpty(), + "Catalog should contain at least one citation style" + ); Map firstStyle = styles.getFirst(); - assertTrue(firstStyle.containsKey("path"), "Style entry should have a path"); - assertTrue(firstStyle.containsKey("title"), "Style entry should have a title"); - assertTrue(firstStyle.containsKey("shortTitle"), "Style entry should have a short title"); - assertTrue(firstStyle.containsKey("isNumeric"), "Style entry should have isNumeric flag"); - assertTrue(firstStyle.containsKey("hasBibliography"), "Style entry should have hasBibliography flag"); - assertTrue(firstStyle.containsKey("usesHangingIndent"), "Style entry should have usesHangingIndent flag"); + assertTrue( + firstStyle.containsKey("path"), + "Style entry should have a path" + ); + assertTrue( + firstStyle.containsKey("title"), + "Style entry should have a title" + ); + assertTrue( + firstStyle.containsKey("shortTitle"), + "Style entry should have a short title" + ); + assertTrue( + firstStyle.containsKey("isNumeric"), + "Style entry should have isNumeric flag" + ); + assertTrue( + firstStyle.containsKey("hasBibliography"), + "Style entry should have hasBibliography flag" + ); + assertTrue( + firstStyle.containsKey("usesHangingIndent"), + "Style entry should have usesHangingIndent flag" + ); } } diff --git a/config/IntelliJ Code Style.xml b/config/IntelliJ Code Style.xml index 1087a14f4b2..cadcbc1e7ea 100644 --- a/config/IntelliJ Code Style.xml +++ b/config/IntelliJ Code Style.xml @@ -3,6 +3,7 @@