diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 64b8e22fbe1..9b10456ba3d 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -21,6 +21,7 @@ env: AstrophysicsDataSystemAPIKey: ${{ secrets.AstrophysicsDataSystemAPIKey }} IEEEAPIKey: ${{ secrets.IEEEAPIKey }} OSXCERT: ${{ secrets.OSX_SIGNING_CERT }} + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.vfs.watch=false jobs: build: @@ -69,12 +70,14 @@ jobs: distribution: 'adopt' if: matrix.os == 'windows-latest' - name: Restore gradle cache - uses: actions/cache@master + uses: actions/cache@v2 with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle7x-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.os }}-gradle- + ${{ runner.os }}-gradle7x- - name: Setup OSX key chain on OSX if: matrix.os == 'macos-latest' uses: apple-actions/import-codesign-certs@v1 diff --git a/.github/workflows/refresh-journal-lists.yml b/.github/workflows/refresh-journal-lists.yml index cef2c760cec..a144641e950 100644 --- a/.github/workflows/refresh-journal-lists.yml +++ b/.github/workflows/refresh-journal-lists.yml @@ -43,10 +43,12 @@ jobs: mkdir -p $GITHUB_WORKSPACE/build/journals cp * $GITHUB_WORKSPACE/build/journals/ + # ensure that the .java classes are the most recent ones + cp $GITHUB_WORKSPACE/src/main/java/org/jabref/logic/journals/* $GITHUB_WORKSPACE/buildSrc/src/copied/java/org/jabref/logic/journals + # create .mv file cd $GITHUB_WORKSPACE ./gradlew generateJournalAbbreviationList - - uses: peter-evans/create-pull-request@v3 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tests-fetchers.yml b/.github/workflows/tests-fetchers.yml index 5c7ccf52bcd..769d1b89fb7 100644 --- a/.github/workflows/tests-fetchers.yml +++ b/.github/workflows/tests-fetchers.yml @@ -38,20 +38,15 @@ jobs: with: java-version: 14 distribution: 'adopt' - - uses: actions/cache@v1 + - uses: actions/cache@v2 name: Restore gradle cache with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.OS }}-gradle-${{ env.cache-name }}- - ${{ runner.OS }}-gradle- - ${{ runner.OS }}- - - uses: actions/cache@v1 - name: Restore gradle wrapper - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + ${{ runner.os }}-gradle- - name: Run fetcher tests run: ./gradlew fetcherTest env: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 82a4af593a9..9dbeb6a92b2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,20 +28,15 @@ jobs: with: java-version: 14 distribution: 'adopt' - - uses: actions/cache@v1 - name: Restore gradle cache + - name: Restore gradle cache + uses: actions/cache@v2 with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle7-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.OS }}-gradle-${{ env.cache-name }}- - ${{ runner.OS }}-gradle- - ${{ runner.OS }}- - - uses: actions/cache@v1 - name: Restore gradle wrapper - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + ${{ runner.os }}-gradle7- - name: Run check style reporter uses: nikitasavinov/checkstyle-action@master with: @@ -65,20 +60,15 @@ jobs: with: java-version: 14 distribution: 'adopt' - - uses: actions/cache@v1 + - uses: actions/cache@v2 name: Restore gradle cache with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle7-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.OS }}-gradle-${{ env.cache-name }}- - ${{ runner.OS }}-gradle- - ${{ runner.OS }}- - - uses: actions/cache@v1 - name: Restore gradle wrapper - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + ${{ runner.os }}-gradle7- - name: Run tests run: xvfb-run --auto-servernum ./gradlew check -x checkstyleJmh -x checkstyleMain -x checkstyleTest env: @@ -110,20 +100,15 @@ jobs: with: java-version: 14 distribution: 'adopt' - - uses: actions/cache@v1 - name: Restore gradle cache + - name: Restore gradle cache + uses: actions/cache@v2 with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle7-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.OS }}-gradle-${{ env.cache-name }}- - ${{ runner.OS }}-gradle- - ${{ runner.OS }}- - - uses: actions/cache@v1 - name: Restore gradle wrapper - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + ${{ runner.os }}-gradle7- - name: Run tests on PostgreSQL run: ./gradlew databaseTest --rerun-tasks env: @@ -157,20 +142,15 @@ jobs: with: java-version: 14 distribution: 'adopt' - - uses: actions/cache@v1 + - uses: actions/cache@v2 name: Restore gradle cache with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle7-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.OS }}-gradle-${{ env.cache-name }}- - ${{ runner.OS }}-gradle- - ${{ runner.OS }}- - - uses: actions/cache@v1 - name: Restore gradle wrapper - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + ${{ runner.os }}-gradle7- - name: Run GUI tests run: xvfb-run --auto-servernum ./gradlew guiTest env: @@ -208,20 +188,15 @@ jobs: with: java-version: 14 distribution: 'adopt' - - uses: actions/cache@v1 - name: Restore gradle cache + - name: Restore gradle cache + uses: actions/cache@v2 with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle7-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.OS }}-gradle-${{ env.cache-name }}- - ${{ runner.OS }}-gradle- - ${{ runner.OS }}- - - uses: actions/cache@v1 - name: Restore gradle wrapper - with: - path: ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + ${{ runner.os }}-gradle7- - name: Update test coverage metrics if: ${{ steps.checksecrets.outputs.secretspresent }} run: xvfb-run --auto-servernum ./gradlew jacocoTestReport && bash <(curl -s https://codecov.io/bash); diff --git a/.gitignore b/.gitignore index ba242f57346..fd187d3f735 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # no generated files in version control src/main/gen/ src/main/generated/ +src-gen/ # private data /buildres/jabref-cert-2016.p12 diff --git a/build.gradle b/build.gradle index 24da247ae4f..e2c51041907 100644 --- a/build.gradle +++ b/build.gradle @@ -9,25 +9,37 @@ import org.jabref.build.xjc.XjcTask plugins { id 'application' + id "com.simonharrer.modernizer" version '2.1.0-1' + id 'me.champeau.gradle.jmh' version '0.5.3' + id 'com.github.ben-manes.versions' version '0.38.0' - id 'org.javamodularity.moduleplugin' version '1.7.0' + + // 1.8.2 does not work in our case (tends to be buggy) + // See https://github.com/java9-modularity/gradle-modules-plugin/issues/188 for details + id 'org.javamodularity.moduleplugin' version '1.8.1' + id 'org.openjfx.javafxplugin' version '0.0.9' + id 'org.beryx.jlink' version '2.23.7' + // nicer test outputs during running and completion // Homepage: https://github.com/radarsh/gradle-test-logger-plugin id 'com.adarshr.test-logger' version '3.0.0' + + id 'jacoco' + + id 'checkstyle' + + id 'project-report' + + id 'idea' } -gradle.startParameter.showStacktrace = org.gradle.api.logging.configuration.ShowStacktrace.ALWAYS +// Enable following for debugging +// gradle.startParameter.showStacktrace = org.gradle.api.logging.configuration.ShowStacktrace. -apply plugin: 'java' -apply plugin: 'application' -apply plugin: 'project-report' -apply plugin: 'jacoco' -apply plugin: 'me.champeau.gradle.jmh' -apply plugin: 'checkstyle' apply plugin: XjcPlugin apply from: 'eclipse.gradle' @@ -38,11 +50,15 @@ version = project.findProperty('projVersion') ?: '100.0.0' java { sourceCompatibility = JavaVersion.VERSION_14 targetCompatibility = JavaVersion.VERSION_14 + + // Workaround needed for Eclipse, probably because of https://github.com/gradle/gradle/issues/16922 + // Should be removed as soon as Gradle 7.0.1 is released ( https://github.com/gradle/gradle/issues/16922#issuecomment-828217060 ) + modularity.inferModulePath.set(false) } application { - mainClassName = "org.jabref.gui.JabRefLauncher" - mainModule = 'org.jabref' + mainClass.set('org.jabref.gui.JabRefLauncher') + mainModule.set('org.jabref') } // TODO: Ugly workaround to temporarily ignore build errors to dependencies of latex2unicode @@ -58,9 +74,9 @@ modularity.disableEffectiveArgumentsAdjustment() sourceSets { main { java { - srcDirs = ["src/main/java", "src/main/generated"] + // src-gen reasoning: https://stackoverflow.com/a/64612308/873282 + srcDirs = ["src/main/java", "src-gen/main/java"] } - resources { srcDirs = ["src/main/java", "src/main/resources"] } @@ -77,7 +93,7 @@ sourceSets { repositories { mavenLocal() - jcenter() + mavenCentral() maven { url 'https://oss.sonatype.org/content/groups/public' } maven { url 'https://repository.apache.org/snapshots' } } @@ -88,6 +104,7 @@ configurations { // TODO: Remove the following workaround for split error messages such as // error: module java.xml.bind reads package javax.annotation from both jsr305 and java.annotation compile { + extendsFrom implementation exclude group: "javax.activation" } } @@ -202,12 +219,12 @@ dependencies { testImplementation 'org.junit.platform:junit-platform-launcher:1.7.1' testImplementation 'net.bytebuddy:byte-buddy-parent:1.11.0' - testRuntime group: 'org.apache.logging.log4j', name: 'log4j-core', version: '3.0.0-SNAPSHOT' - testRuntime group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '3.0.0-SNAPSHOT' + testRuntimeOnly group: 'org.apache.logging.log4j', name: 'log4j-core', version: '3.0.0-SNAPSHOT' + testRuntimeOnly group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '3.0.0-SNAPSHOT' testImplementation 'org.mockito:mockito-core:3.9.0' testImplementation 'org.xmlunit:xmlunit-core:2.8.2' testImplementation 'org.xmlunit:xmlunit-matchers:2.8.2' - testRuntime 'com.tngtech.archunit:archunit-junit5-engine:0.18.0' + testRuntimeOnly 'com.tngtech.archunit:archunit-junit5-engine:0.18.0' testImplementation 'com.tngtech.archunit:archunit-junit5-api:0.17.0' testImplementation "org.testfx:testfx-core:4.0.17-alpha-SNAPSHOT" testImplementation "org.testfx:testfx-junit5:4.0.17-alpha-SNAPSHOT" @@ -222,7 +239,7 @@ dependencyUpdates { } // We have some dependencies which cannot be updated due to various reasons. -dependencyUpdates.resolutionStrategy = { +dependencyUpdates.resolutionStrategy { componentSelection { rules -> rules.all { ComponentSelection selection -> boolean rejected = ['alpha', 'snapshot', 'beta', 'rc', 'cr', 'm', 'preview', 'b', 'ea'].any { qualifier -> @@ -259,6 +276,7 @@ task checkOutdatedDependencies(dependsOn: dependencyUpdates) { clean { delete "src/main/generated" + delete "src-gen" } processResources { @@ -266,6 +284,7 @@ processResources { if (gradle.taskGraph.hasTask(":jpackage")) { logger.info('Adding buildres/csl to resources') from("buildres/csl") + duplicatesStrategy = DuplicatesStrategy.EXCLUDE } } @@ -299,24 +318,26 @@ task generateSource(dependsOn: ["generateBstGrammarSource", description 'Generates all necessary (Java) source files.' } -task generateBstGrammarSource(type: JavaExec) { +tasks.register("generateBstGrammarSource", JavaExec) { main = "org.antlr.Tool" classpath = configurations.antlr3 group = "JabRef" description = 'Generates BstLexer.java and BstParser.java from the Bst.g grammar file using antlr3.' inputs.dir('src/main/antlr3/org/jabref/bst/') - args = ["-o", "$projectDir/src/main/generated/org/jabref/logic/bst/" , "$projectDir/src/main/antlr3/org/jabref/bst/Bst.g" ] + outputs.dir("src-gen/main/java/org/jabref/logic/bst/") + args = ["-o", "src-gen/main/java/org/jabref/logic/bst/" , "$projectDir/src/main/antlr3/org/jabref/bst/Bst.g" ] } -task generateSearchGrammarSource(type: JavaExec) { +tasks.register("generateSearchGrammarSource", JavaExec) { main = "org.antlr.v4.Tool" classpath = configurations.antlr4 group = 'JabRef' description = "Generates java files for Search.g antlr4." inputs.dir("src/main/antlr4/org/jabref/search/") - args = ["-o","$projectDir/src/main/generated/org/jabref/search" , "-visitor", "-no-listener", "-package", "org.jabref.search", "$projectDir/src/main/antlr4/org/jabref/search/Search.g4"] + outputs.dir("src-gen/main/java/org/jabref/search/") + args = ["-o","src-gen/main/java/org/jabref/search" , "-visitor", "-no-listener", "-package", "org.jabref.search", "$projectDir/src/main/antlr4/org/jabref/search/Search.g4"] } task generateMedlineSource(type: XjcTask) { @@ -324,7 +345,7 @@ task generateMedlineSource(type: XjcTask) { description = "Generates java files for the medline importer." schemaFile = "src/main/resources/xjc/medline/medline.xsd" - outputDirectory = "src/main/generated" + outputDirectory = "src-gen/main/java" javaPackage = "org.jabref.logic.importer.fileformat.medline" } @@ -333,7 +354,7 @@ task generateBibtexmlSource(type: XjcTask) { description = "Generates java files for the bibtexml importer." schemaFile = "src/main/resources/xjc/bibtexml/bibtexml.xsd" - outputDirectory = "src/main/generated/" + outputDirectory = "src-gen/main/java/" javaPackage = "org.jabref.logic.importer.fileformat.bibtexml" } @@ -342,7 +363,7 @@ task generateEndnoteSource(type: XjcTask) { description = "Generates java files for the endnote importer." schemaFile = "src/main/resources/xjc/endnote/endnote.xsd" - outputDirectory = "src/main/generated/" + outputDirectory = "src-gen/main/java/" javaPackage = "org.jabref.logic.importer.fileformat.endnote" } @@ -352,7 +373,7 @@ task generateModsSource(type: XjcTask) { schemaFile = "src/main/resources/xjc/mods/mods-3-7.xsd" bindingFile = "src/main/resources/xjc/mods/mods-binding.xjb" - outputDirectory = "src/main/generated/" + outputDirectory = "src-gen/main/java" javaPackage = "org.jabref.logic.importer.fileformat.mods" arguments = '-npa' } @@ -361,7 +382,10 @@ task generateJournalAbbreviationList(type: JournalAbbreviationConverter) { group = 'JabRef' description = "Converts the comma-separated journal abbreviation file to a H2 MVStore." + // This directory is filled by "refresh-journal-lists.yml" + // It takes the contents of https://github.com/JabRef/abbrv.jabref.org.git inputDir = file("build/journals") + outputDir = file("src/main/resources/journals") } @@ -373,7 +397,7 @@ compileJava { options.compilerArgs << "-Xlint:none" dependsOn "generateSource" - options.annotationProcessorGeneratedSourcesDirectory = file("${projectDir}/src/main/generated") + options.annotationProcessorGeneratedSourcesDirectory = file("src-gen/main/java") moduleOptions { // TODO: Remove access to internal api @@ -435,7 +459,6 @@ javadoc { } } - test { useJUnitPlatform { excludeTags 'DatabaseTest', 'FetcherTest', 'GUITest' @@ -549,7 +572,7 @@ task deleteInstallerTemp(type: Delete) { jpackage.dependsOn deleteInstallerTemp jlink { - options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'] + addOptions('--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages') launcher { name = 'JabRef' } @@ -568,30 +591,30 @@ jlink { // The module descriptor automatically generated by the plugin for the merged module contained some invalid entries. // Execute ./gradlew suggestMergedModuleInfo and include the suggested directives here. mergedModule { - requires 'java.compiler'; - requires 'java.datatransfer'; - requires 'java.desktop'; - requires 'java.logging'; - requires 'java.management'; - requires 'java.naming'; - requires 'java.net.http'; - requires 'java.scripting'; - requires 'java.security.jgss'; - requires 'java.security.sasl'; - requires 'java.sql'; - requires 'java.sql.rowset'; - requires 'java.transaction.xa'; - requires 'java.rmi'; - requires 'java.xml'; - requires 'jdk.jfr'; - requires 'jdk.jsobject'; - requires 'jdk.unsupported'; - requires 'jdk.unsupported.desktop'; - requires 'jdk.security.jgss'; - requires 'jdk.xml.dom'; - requires 'com.google.gson'; - requires 'com.sun.xml.fastinfoset'; - requires 'com.sun.xml.txw2'; + requires 'java.compiler' + requires 'java.datatransfer' + requires 'java.desktop' + requires 'java.logging' + requires 'java.management' + requires 'java.naming' + requires 'java.net.http' + requires 'java.scripting' + requires 'java.security.jgss' + requires 'java.security.sasl' + requires 'java.sql' + requires 'java.sql.rowset' + requires 'java.transaction.xa' + requires 'java.rmi' + requires 'java.xml' + requires 'jdk.jfr' + requires 'jdk.jsobject' + requires 'jdk.unsupported' + requires 'jdk.unsupported.desktop' + requires 'jdk.security.jgss' + requires 'jdk.xml.dom' + requires 'com.google.gson' + requires 'com.sun.xml.fastinfoset' + requires 'com.sun.xml.txw2' requires 'org.slf4j' uses 'org.apache.logging.log4j.util.PropertySource' uses 'org.apache.logging.log4j.core.util.WatchEventService' @@ -605,10 +628,10 @@ jlink { uses 'org.mariadb.jdbc.authentication.AuthenticationPlugin' uses 'org.mariadb.jdbc.tls.TlsSocketPlugin' uses 'org.mariadb.jdbc.LocalInfileInterceptor' - uses 'org.eclipse.jgit.transport.SshSessionFactory'; - uses 'org.eclipse.jgit.lib.GpgSigner'; + uses 'org.eclipse.jgit.transport.SshSessionFactory' + uses 'org.eclipse.jgit.lib.GpgSigner' uses 'javax.xml.bind.JAXBContextFactory' - provides 'org.apache.lucene.codecs.DocValuesFormat' with 'org.apache.lucene.codecs.lucene80.Lucene80DocValuesFormat'; + provides 'org.apache.lucene.codecs.DocValuesFormat' with 'org.apache.lucene.codecs.lucene80.Lucene80DocValuesFormat' provides 'javax.annotation.processing.Processor' with 'org.apache.logging.log4j.plugins.processor.PluginProcessor' provides 'org.controlsfx.glyphfont.GlyphFont' with 'org.controlsfx.glyphfont.FontAwesome' provides 'org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory' with 'org.apache.logging.log4j.core.message.ExtendedThreadInfoFactory' @@ -639,8 +662,6 @@ jlink { } jpackage { - // In order for this to work, you need to dowload jpackage from https://jdk.java.net/jpackage/ - // and put the path to the jdk-14 folder in the environment variable BADASS_JLINK_JPACKAGE_HOME outputDir = "distribution" if (OperatingSystem.current().isWindows()) { @@ -758,5 +779,3 @@ task downloadDependencies { } } } - - diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 9f99d5fbc0a..fb4bcb94721 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,19 +1,20 @@ apply plugin: 'java' repositories { - jcenter() + mavenLocal() + mavenCentral() } dependencies { - compile 'com.h2database:h2-mvstore:1.4.200' - compile 'org.apache.commons:commons-csv:1.8' - compile 'org.slf4j:slf4j-api:2.0.0-alpha1' + implementation 'com.h2database:h2-mvstore:1.4.200' + implementation 'org.apache.commons:commons-csv:1.8' + implementation 'org.slf4j:slf4j-api:2.0.0-alpha1' } sourceSets{ main { java { - srcDir "${project.rootDir}/../src/main/java/org/jabref/logic/journals" + srcDir "src/copied" } } } diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/Abbreviation.java b/buildSrc/src/copied/java/org/jabref/logic/journals/Abbreviation.java new file mode 100644 index 00000000000..b6c8d4ddf89 --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/Abbreviation.java @@ -0,0 +1,88 @@ +package org.jabref.logic.journals; + +import java.util.Objects; + +public class Abbreviation implements Comparable { + + private final String name; + private final String abbreviation; + private final String shortestUniqueAbbreviation; + + public Abbreviation(String name, String abbreviation) { + this(name, abbreviation, ""); + } + + public Abbreviation(String name, String abbreviation, String shortestUniqueAbbreviation) { + this.name = name; + this.abbreviation = abbreviation; + this.shortestUniqueAbbreviation = shortestUniqueAbbreviation.trim(); + } + + public String getName() { + return name; + } + + public String getAbbreviation() { + return abbreviation; + } + + public String getShortestUniqueAbbreviation() { + String result = shortestUniqueAbbreviation; + if (result.isEmpty()) { + return getAbbreviation(); + } + return result; + } + + public String getMedlineAbbreviation() { + return getAbbreviation().replace(".", " ").replace(" ", " ").trim(); + } + + @Override + public int compareTo(Abbreviation toCompare) { + return getName().compareTo(toCompare.getName()); + } + + public String getNext(String current) { + String currentTrimmed = current.trim(); + + if (getMedlineAbbreviation().equals(currentTrimmed)) { + return getShortestUniqueAbbreviation().equals(getAbbreviation()) ? getName() : getShortestUniqueAbbreviation(); + } else if (getShortestUniqueAbbreviation().equals(currentTrimmed) && !getShortestUniqueAbbreviation().equals(getAbbreviation())) { + return getName(); + } else if (getName().equals(currentTrimmed)) { + return getAbbreviation(); + } else { + return getMedlineAbbreviation(); + } + } + + @Override + public String toString() { + return String.format("Abbreviation{name=%s, abbreviation=%s, medlineAbbreviation=%s, shortestUniqueAbbreviation=%s}", + this.name, + this.abbreviation, + this.getMedlineAbbreviation(), + this.shortestUniqueAbbreviation); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + Abbreviation that = (Abbreviation) obj; + + return Objects.equals(getName(), that.getName()); + } + + @Override + public int hashCode() { + return Objects.hash(getName()); + } +} diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationFormat.java b/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationFormat.java new file mode 100644 index 00000000000..e4713773a3d --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationFormat.java @@ -0,0 +1,22 @@ +package org.jabref.logic.journals; + +import org.apache.commons.csv.CSVFormat; + +public final class AbbreviationFormat { + + public static final char DELIMITER = ';'; + public static final char ESCAPE = '\\'; + public static final char QUOTE = '"'; + + private AbbreviationFormat() { + } + + public static CSVFormat getCSVFormat() { + return CSVFormat.DEFAULT + .withIgnoreEmptyLines(true) + .withDelimiter(DELIMITER) + .withEscape(ESCAPE) + .withQuote(QUOTE) + .withTrim(); + } +} diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationParser.java b/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationParser.java new file mode 100644 index 00000000000..6506469d7da --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationParser.java @@ -0,0 +1,76 @@ +package org.jabref.logic.journals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Reads abbreviation files (CSV format) into a list of Abbreviations. + */ +public class AbbreviationParser { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbbreviationParser.class); + + private final Set abbreviations = new HashSet<>(5000); + + public void readJournalListFromResource(String resourceFileName) { + try (InputStream stream = JournalAbbreviationRepository.class.getResourceAsStream(resourceFileName); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { + readJournalList(reader); + } catch (IOException e) { + LOGGER.error(String.format("Could not read journal list from file %s", resourceFileName), e); + } + } + + public void readJournalListFromFile(Path file) throws IOException { + readJournalListFromFile(file, StandardCharsets.UTF_8); + } + + public void readJournalListFromFile(Path file, Charset encoding) throws IOException { + try (BufferedReader reader = Files.newBufferedReader(file, encoding)) { + readJournalList(reader); + } + } + + /** + * Read the given file, which should contain a list of journal names and their abbreviations. Each line should be + * formatted as: "Full Journal Name;Abbr. Journal Name;[Shortest Unique Abbreviation]" + * + * @param reader a given file into a Reader object + */ + private void readJournalList(Reader reader) throws IOException { + try (CSVParser csvParser = new CSVParser(reader, AbbreviationFormat.getCSVFormat())) { + for (CSVRecord csvRecord : csvParser) { + String name = csvRecord.size() > 0 ? csvRecord.get(0) : ""; + String abbreviation = csvRecord.size() > 1 ? csvRecord.get(1) : ""; + String shortestUniqueAbbreviation = csvRecord.size() > 2 ? csvRecord.get(2) : ""; + + // Check name and abbreviation + if (name.isEmpty() || abbreviation.isEmpty()) { + return; + } + + abbreviations.add(new Abbreviation(name, abbreviation, shortestUniqueAbbreviation)); + } + } + } + + public List getAbbreviations() { + return new LinkedList<>(abbreviations); + } +} diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationWriter.java b/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationWriter.java new file mode 100644 index 00000000000..d922ddd488d --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/AbbreviationWriter.java @@ -0,0 +1,39 @@ +package org.jabref.logic.journals; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.apache.commons.csv.CSVPrinter; + +/** + * This class provides handy static methods to save abbreviations to the file system. + */ +public final class AbbreviationWriter { + + private AbbreviationWriter() { + } + + /** + * This method will write the list of abbreviations to a file on the file system specified by the given path. If the + * file already exists its content will be overridden, otherwise a new file will be created. + * + * @param path to a file (doesn't have to exist just yet) + * @param abbreviations as a list specifying which entries should be written + */ + public static void writeOrCreate(Path path, List abbreviations, Charset encoding) throws IOException { + try (OutputStreamWriter writer = new OutputStreamWriter(Files.newOutputStream(path), encoding); + CSVPrinter csvPrinter = new CSVPrinter(writer, AbbreviationFormat.getCSVFormat())) { + for (Abbreviation entry : abbreviations) { + if (entry.getShortestUniqueAbbreviation().isEmpty()) { + csvPrinter.printRecord(entry.getName(), entry.getAbbreviation()); + } else { + csvPrinter.printRecord(entry.getName(), entry.getAbbreviation(), entry.getShortestUniqueAbbreviation()); + } + } + } + } +} diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationLoader.java b/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationLoader.java new file mode 100644 index 00000000000..72f0664b046 --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationLoader.java @@ -0,0 +1,54 @@ +package org.jabref.logic.journals; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JournalAbbreviationLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(JournalAbbreviationLoader.class); + + public static List readJournalListFromFile(Path file) throws IOException { + LOGGER.debug(String.format("Reading journal list from file %s", file)); + AbbreviationParser parser = new AbbreviationParser(); + parser.readJournalListFromFile(file); + return parser.getAbbreviations(); + } + + public static JournalAbbreviationRepository loadRepository(JournalAbbreviationPreferences journalAbbreviationPreferences) { + JournalAbbreviationRepository repository; + // Initialize with built-in list + try { + Path tempJournalList = Files.createTempDirectory("journal").resolve("journalList.mv"); + Files.copy(JournalAbbreviationRepository.class.getResourceAsStream("/journals/journalList.mv"), tempJournalList); + repository = new JournalAbbreviationRepository(tempJournalList); + } catch (IOException e) { + LOGGER.error("Error while copying journal list", e); + return null; + } + + // Read external lists + List lists = journalAbbreviationPreferences.getExternalJournalLists(); + if (!(lists.isEmpty())) { + Collections.reverse(lists); + for (String filename : lists) { + try { + repository.addCustomAbbreviations(readJournalListFromFile(Path.of(filename))); + } catch (IOException e) { + LOGGER.error(String.format("Cannot read external journal list file %s", filename), e); + } + } + } + return repository; + } + + public static JournalAbbreviationRepository loadBuiltInRepository() { + return loadRepository(new JournalAbbreviationPreferences(Collections.emptyList(), StandardCharsets.UTF_8)); + } +} diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationPreferences.java b/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationPreferences.java new file mode 100644 index 00000000000..300592b0172 --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationPreferences.java @@ -0,0 +1,27 @@ +package org.jabref.logic.journals; + +import java.nio.charset.Charset; +import java.util.List; + +public class JournalAbbreviationPreferences { + + private final Charset defaultEncoding; + private List externalJournalLists; + + public JournalAbbreviationPreferences(List externalJournalLists, Charset defaultEncoding) { + this.externalJournalLists = externalJournalLists; + this.defaultEncoding = defaultEncoding; + } + + public List getExternalJournalLists() { + return externalJournalLists; + } + + public void setExternalJournalLists(List externalJournalLists) { + this.externalJournalLists = externalJournalLists; + } + + public Charset getDefaultEncoding() { + return defaultEncoding; + } +} diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationRepository.java b/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationRepository.java new file mode 100644 index 00000000000..523e1323be1 --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/JournalAbbreviationRepository.java @@ -0,0 +1,133 @@ +package org.jabref.logic.journals; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.h2.mvstore.MVMap; +import org.h2.mvstore.MVStore; + +/** + * A repository for all journal abbreviations, including add and find methods. + */ +public class JournalAbbreviationRepository { + + private final MVMap fullToAbbreviation; + private final MVMap abbreviationToFull; + private final List customAbbreviations; + + public JournalAbbreviationRepository(Path journalList) { + MVStore store = new MVStore.Builder().readOnly().fileName(journalList.toAbsolutePath().toString()).open(); + this.fullToAbbreviation = store.openMap("FullToAbbreviation"); + this.abbreviationToFull = store.openMap("AbbreviationToFull"); + this.customAbbreviations = new ArrayList<>(); + } + + private static boolean isMatched(String name, Abbreviation abbreviation) { + return name.equalsIgnoreCase(abbreviation.getName()) + || name.equalsIgnoreCase(abbreviation.getAbbreviation()) + || name.equalsIgnoreCase(abbreviation.getMedlineAbbreviation()) + || name.equalsIgnoreCase(abbreviation.getShortestUniqueAbbreviation()); + } + + private static boolean isMatchedAbbreviated(String name, Abbreviation abbreviation) { + boolean isAbbreviated = name.equalsIgnoreCase(abbreviation.getAbbreviation()) + || name.equalsIgnoreCase(abbreviation.getMedlineAbbreviation()) + || name.equalsIgnoreCase(abbreviation.getShortestUniqueAbbreviation()); + boolean isExpanded = name.equalsIgnoreCase(abbreviation.getName()); + return isAbbreviated && !isExpanded; + } + + /** + * Returns true if the given journal name is contained in the list either in its full form (e.g Physical Review + * Letters) or its abbreviated form (e.g. Phys. Rev. Lett.). + */ + public boolean isKnownName(String journalName) { + String journal = journalName.trim(); + + boolean isKnown = customAbbreviations.stream().anyMatch(abbreviation -> isMatched(journal, abbreviation)); + if (isKnown) { + return true; + } + + return fullToAbbreviation.containsKey(journal) || abbreviationToFull.containsKey(journal); + } + + /** + * Returns true if the given journal name is in its abbreviated form (e.g. Phys. Rev. Lett.). The test is strict, + * i.e. journals whose abbreviation is the same as the full name are not considered + */ + public boolean isAbbreviatedName(String journalName) { + String journal = journalName.trim(); + + return customAbbreviations.stream().anyMatch(abbreviation -> isMatchedAbbreviated(journal, abbreviation)) + || abbreviationToFull.containsKey(journal); + } + + /** + * Attempts to get the abbreviation of the journal given. + * + * @param input The journal name (either abbreviated or full name). + */ + public Optional get(String input) { + String journal = input.trim(); + + Optional customAbbreviation = customAbbreviations.stream() + .filter(abbreviation -> isMatched(journal, abbreviation)) + .findAny(); + if (customAbbreviation.isPresent()) { + return customAbbreviation; + } + + return Optional.ofNullable(fullToAbbreviation.get(journal)) + .map(abbreviation -> new Abbreviation(journal, abbreviation)) + .or(() -> Optional.ofNullable(abbreviationToFull.get(journal)).map(fullName -> new Abbreviation(fullName, journal))); + } + + public void addCustomAbbreviation(Abbreviation abbreviation) { + Objects.requireNonNull(abbreviation); + + // We do not want to keep duplicates, thus remove the old abbreviation + // (abbreviation equality is tested on name only, so we cannot use a Set instead) + customAbbreviations.remove(abbreviation); + customAbbreviations.add(abbreviation); + } + + public List getCustomAbbreviations() { + return customAbbreviations; + } + + public void addCustomAbbreviations(Collection abbreviationsToAdd) { + abbreviationsToAdd.forEach(this::addCustomAbbreviation); + } + + public Optional getNextAbbreviation(String text) { + return get(text).map(abbreviation -> abbreviation.getNext(text)); + } + + public Optional getDefaultAbbreviation(String text) { + return get(text).map(Abbreviation::getAbbreviation); + } + + public Optional getMedlineAbbreviation(String text) { + return get(text).map(Abbreviation::getMedlineAbbreviation); + } + + public Optional getShortestUniqueAbbreviation(String text) { + return get(text).map(Abbreviation::getShortestUniqueAbbreviation); + } + + public Set getFullNames() { + return fullToAbbreviation.keySet(); + } + + public List getAllLoaded() { + return fullToAbbreviation.entrySet().stream().map(entry -> + new Abbreviation(entry.getKey(), entry.getValue())).collect(Collectors.toList()); + } +} diff --git a/buildSrc/src/copied/java/org/jabref/logic/journals/package-info.java b/buildSrc/src/copied/java/org/jabref/logic/journals/package-info.java new file mode 100644 index 00000000000..7a967bbd91d --- /dev/null +++ b/buildSrc/src/copied/java/org/jabref/logic/journals/package-info.java @@ -0,0 +1,7 @@ +/** + * The files in this directory are copied from JabRef's main source. + * We need top have a copy, because + * a) symblinks do not work on git for windows out of the box (https://stackoverflow.com/a/59761201/873282) + * b) using a source directory of another project causes issues in i) gradle 7, ii) IntelliJ 2020 and later + */ +package org.jabref.logic.journals; diff --git a/buildSrc/src/main/groovy/org/jabref/build/JournalAbbreviationConverter.groovy b/buildSrc/src/main/groovy/org/jabref/build/JournalAbbreviationConverter.groovy index 85fabd28569..bfeec72191b 100644 --- a/buildSrc/src/main/groovy/org/jabref/build/JournalAbbreviationConverter.groovy +++ b/buildSrc/src/main/groovy/org/jabref/build/JournalAbbreviationConverter.groovy @@ -22,10 +22,13 @@ abstract class JournalAbbreviationConverter extends DefaultTask { def targetFile = outputDir.file("journalList.mv").get().asFile targetFile.delete() MVStore.open(targetFile.toString()).withCloseable { store -> + MVMap fullToAbbreviation = store.openMap("FullToAbbreviation") MVMap abbreviationToFull = store.openMap("AbbreviationToFull") inputDir.getAsFileTree().filter({ File f -> f.name.endsWith(".csv") }).getFiles().each { file -> + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + def abbreviations = JournalAbbreviationLoader.readJournalListFromFile(file.toPath()) fullToAbbreviation.putAll( abbreviations diff --git a/buildSrc/src/main/groovy/org/jabref/build/xjc/XjcTask.groovy b/buildSrc/src/main/groovy/org/jabref/build/xjc/XjcTask.groovy index 2b6fd9b7bbd..8b68e35ab98 100644 --- a/buildSrc/src/main/groovy/org/jabref/build/xjc/XjcTask.groovy +++ b/buildSrc/src/main/groovy/org/jabref/build/xjc/XjcTask.groovy @@ -2,6 +2,8 @@ package org.jabref.build.xjc import org.gradle.api.DefaultTask import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.Optional import org.gradle.api.tasks.TaskAction @@ -30,7 +32,7 @@ class XjcTask extends DefaultTask { } } - @Input + @InputFile File getSchemaFile() { if (schemaFile == null) { return null @@ -42,6 +44,7 @@ class XjcTask extends DefaultTask { this.schemaFile = schemaFile } + @OutputDirectory File getOutputDirectory() { if (outputDirectory == null) { return null @@ -54,6 +57,7 @@ class XjcTask extends DefaultTask { updateOutput() } + @Input String getJavaPackage() { return javaPackage } @@ -63,6 +67,7 @@ class XjcTask extends DefaultTask { updateOutput() } + @Input String getEncoding() { if(encoding == null ) { // use UTF-8 as default encoding @@ -76,6 +81,7 @@ class XjcTask extends DefaultTask { this.encoding = encoding } + @Input String getArguments() { return arguments } @@ -84,7 +90,7 @@ class XjcTask extends DefaultTask { this.arguments = args } - @Input + @InputFile File getBindingFile() { if (bindingFile == null) { return null diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index 2169d4246f3..471a9f57d82 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -6,6 +6,7 @@ + diff --git a/docs/getting-into-the-code/guidelines-for-setting-up-a-local-workspace.md b/docs/getting-into-the-code/guidelines-for-setting-up-a-local-workspace.md index f17c8b70681..f63c5009c55 100644 --- a/docs/getting-into-the-code/guidelines-for-setting-up-a-local-workspace.md +++ b/docs/getting-into-the-code/guidelines-for-setting-up-a-local-workspace.md @@ -104,17 +104,17 @@ To configure IntelliJ IDEA for developing JabRef, you should first ensure that y After that, you can open `jabref/build.gradle` as a project. It is crucial that Java 15 is used consistently for the JabRef project which includes ensuring the right settings for your project structure, Gradle build, and run configurations. -Ensure you have a Java 15 SDK configured by navigating to **File \| Project Structure \| Platform Settings \| SDKs**. If you don't have one, add a new Java JDK and point it to the location of a JDK 15. +Ensure you have a Java 15 SDK configured by navigating to **File \| Project Structure \| Platform Settings \| SDKs**. If you don't have one, add a new Java JDK and point it to the location of a JDK 15. ![Project Settings](../.gitbook/assets/intellij-choose-jdk-adoptopenjdk-on-windows-project-settings.png) -Navigate to **File \| Project Structure \| Project** and ensure that the projects' SDK is Java 15 +Navigate to **File \| Project Structure \| Project** and ensure that the projects' SDK is Java 15 ![Use JDK 15 as project SDK](../.gitbook/assets/intellij-choose-jdk15-project-default.png) Navigate to **File \| Settings \| Build, Execution, Deployment \| Build Tools \| Gradle** and select the "Project SDK" as the Gradle JVM at the bottom. To prepare IntelliJ's build system two additional steps are required: -* Navigate to **File \| Settings \| Build, Execution, Deployment \| Compiler \| Java Compiler**, and under "Override compiler parameters per-module" add \(\[+\]\) the following compiler arguments for the `JabRef.main` module: +* Navigate to **File \| Settings \| Build, Execution, Deployment \| Compiler \| Java Compiler**, and under "Override compiler parameters per-module" add \(\[+\]\) the following compiler arguments for the `JabRef.main` module. Otherwise, you will get: `java: package com.sun.javafx.scene.control is not visible (package com.sun.javafx.scene.control is declared in module javafx.controls, which does not export it to module org.jabref)` ```text --add-exports=javafx.controls/com.sun.javafx.scene.control=org.jabref @@ -146,8 +146,6 @@ After that a new entry called "jabref \[run\]" will appear in the run configurat #### Using IntelliJ's internal build system -**Note that these steps do not work on IntelliJ 2020.x.**. You have to keep using gradle for executing tasks. See [IDEA-249391](https://youtrack.jetbrains.com/issue/IDEA-249391) for details. - You should use IntelliJ IDEA's internal build system for compiling and running JabRef during development, because it is usually more responsive. Thereby, **it's important** that you understand that JabRef relies on generated sources which are only build through Gradle. Therefore, to build or update these dependencies you need to run the `assemble` Gradle task at least once. To use IntelliJ IDEA's internal build system when you build JabRef through **Build \| Build Project** or use the provided "JabRef Main" run configuration, ensure that @@ -157,7 +155,21 @@ To use IntelliJ IDEA's internal build system when you build JabRef through **Bui ![Ignore the Gradle project "buildSrc"](../.gitbook/assets/intellij-gradle-config-ignore-buildSrc%20%282%29%20%282%29%20%282%29%20%283%29.png) -* Delete `org.jabref.gui.logging.plugins.Log4jPlugins` \(location: `generated\org\jabref\gui\logging\plugins\Log4jPlugins.java`\). Otherwise, you will see following error: +* Add `src-gen` as root: + + 1. Right click on the project "jabref". + 1. Select "Open Module Settings" + 1. Expand "JabRef" + 1. Select "main" + 1. Select tab "Sources" + 1. Click "+ Add Content Root" + 1. Select the `src-gen` directory + 1. Click "OK". When expanding "main", "java" should have been selected as source + 1. Click "OK" to save the changes + +* In case the above step does not work, run with gradle, import gradle project again, and try again. + +* Delete `org.jabref.gui.logging.plugins.Log4jPlugins` \(location: `src-gen/main/java/org/jabref/gui/logging/plugins/Log4jPlugins.java`\). Otherwise, you will see following error: ```text Error:java: Unable to create Plugin Service Class org.jabref.gui.logging.plugins.Log4jPlugins @@ -171,7 +183,9 @@ To use IntelliJ IDEA's internal build system when you build JabRef through **Bui Essentially, you now have the best of both worlds: You can run Gradle tasks using the Gradle Tool Window and unless you haven't made changes to input files that generate sources, you can compile and run with IntelliJ's faster internal build system. -In case all steps are followed, and there are still issues with `SearchBaseVisitor` \(e.g., `Error:(16, 25) java: package org.jabref.search does not exist`\), you have to delete `generated\org\jabref\gui\logging\plugins\Log4jPlugins.java`. This is independent of having enabled or disabled Annotation Processing \(see above at "Enable Annotation Processing"\). +In case all steps are followed, and there are still issues with `SearchBaseVisitor` \(e.g., `Error:(16, 25) java: package org.jabref.search does not exist`\), you have to delete `src\main\generated\org\jabref\gui\logging\plugins\Log4jPlugins.java`. This is independent of having enabled or disabled Annotation Processing \(see above at "Enable Annotation Processing"\). + +~~Note that the above steps might not work on IntelliJ 2020.x.**. You have to keep using gradle for executing tasks. See [IDEA-249391](https://youtrack.jetbrains.com/issue/IDEA-249391) for details.~~ #### Using JabRef's code style @@ -271,11 +285,18 @@ Another indication is following output java.lang.UnsupportedClassVersionError: org/javamodularity/moduleplugin/ModuleSystemPlugin has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 ``` -### Problems with generated source files +### Issues with generated source files In rare cases you might encounter problems due to out-dated automatically generated source files. Running `./gradlew clean` deletes these old copies. Do not forget to run at least `./gradlew eclipse` or `./gradlew build` afterwards to regenerate the source files. +`` + +### Issues with `buildSrc` + +1. Open the context menu of `buildSrc`. +1. Select "Load/Unload modules". +1. Unload `jabRef.buildSrc`. -### Problems with openjfx libraries in local maven repository +### Issues with openjfx libraries in local maven repository There might be problems with building if you have openjfx libraries in local maven repository, resulting in errors like this: diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132ea3..d6aa5ac2215 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionSha256Sum=eb8b89184261025b0430f5b2233701ff1377f96da1ef5e278af6ae8bac5cc305 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists