diff --git a/Dockerfile b/Dockerfile index 672619d..72fe7d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ CMD mvn -B -q checkstyle:check | \ # ===== stage 2 ===== FROM setup-env AS build-jar -RUN mvn clean compile assembly:single +RUN mvn clean package # ===== stage 3 ===== @@ -32,7 +32,7 @@ FROM eclipse-temurin:11-jre-focal ARG REPO_DIR -ARG JAR_FILE=target/update-dois-*-jar-with-dependencies.jar +ARG JAR_FILE=target/update-dois-jar-with-dependencies.jar WORKDIR ${REPO_DIR} diff --git a/Jenkinsfile b/Jenkinsfile index fdff7a6..cd5d2fb 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -17,6 +17,7 @@ pipeline { } } } + // This stage backs up the gk_central (on curator server) and release_current databases before they are modified. stage('Setup: Back up DBs'){ steps{ @@ -30,14 +31,16 @@ pipeline { } } } + // This stage builds the jar file using maven. stage('Setup: Build jar file'){ steps{ script{ - utils.buildJarFile() + sh "mvn clean package -DskipTests" } } } + // This stage executes UpdateDOIs without specifying a 'report' file, which should contain a list of updateable DOIS, as one of the arguments. // This results in test mode behaviour, which includes generating the report file that contains updateable DOIS for release. stage('Main: UpdateDOIs Test Run'){ @@ -45,11 +48,12 @@ pipeline { script{ withCredentials([file(credentialsId: 'Config', variable: 'ConfigFile')]) { sh "touch src/main/resources/UpdateDOIs.report" - sh "java -jar target/update-dois.jar $ConfigFile" + sh "java -jar target/update-dois-jar-with-dependencies.jar $ConfigFile" } } } } + // This stage takes the generated report file and sends it to the curator overseeing release. // Before moving onto the next stage of UpdateDOIs, their confirmation that the contents of the report file are correct is needed. stage('Main: Send email of updateable DOIs to curator'){ @@ -65,6 +69,7 @@ pipeline { } } } + // UpdateDOIs should pause at this stage until the curator confirms the report file is correct. Once they do, respond with 'yes' to the user input form that Jenkins brings up. stage('User Input Required: Confirm DOIs'){ steps{ @@ -79,6 +84,7 @@ pipeline { } } } + // Now that you have curator approval regarding the report file, this step executes the same jar file again -- this time providing the report file as an argument. // With the report file as the second argument, UpdateDOIs executes database modifications. stage('Main: UpdateDOIs'){ @@ -86,11 +92,25 @@ pipeline { script{ withCredentials([file(credentialsId: 'Config', variable: 'ConfigFile')]) { def releaseVersion = utils.getReleaseVersion() - sh "java -jar target/update-dois-*-jar-with-dependencies.jar $ConfigFile doisToBeUpdated-v${releaseVersion}.txt" + sh "java -jar target/update-dois-jar-with-dependencies.jar $ConfigFile doisToBeUpdated-v${releaseVersion}.txt" } } } } + + stage('Post: Verify UpdateDOIs') { + steps { + script { + withCredentials([usernamePassword(credentialsId: 'mySQLUsernamePassword', passwordVariable: 'releasePass', usernameVariable: 'releaseUser')]){ + withCredentials([usernamePassword(credentialsId: 'mySQLCuratorUsernamePassword', passwordVariable: 'curatorPass', usernameVariable: 'curatorUser')]){ + def releaseVersion = utils.getReleaseVersion() + sh "java -jar target/update-dois-verifier-jar-with-dependencies.jar --r $releaseVersion --cu $curatorUser --cp $curatorPass --ru $releaseUser --rp $releasePass --ch curator.reactome.org" + } + } + } + } + } + // This stage backs up the gk_central and release_current databases after they are modified. stage('Post: Backup DBs'){ steps{ @@ -104,6 +124,7 @@ pipeline { } } } + // All databases, logs, and data files generated by this step are compressed before moving them to the Reactome S3 bucket. All files are then deleted. stage('Post: Archive Outputs'){ steps{ @@ -117,16 +138,17 @@ pipeline { } } } + // This sends an email notifying the mailing list that both the UpdateStableIdentifiers and UpdateDOIs steps have completed. This indicates that gk_central can be reopened. stage('Post: Send completion email') { steps{ - script{ - def releaseVersion = utils.getReleaseVersion() + script{ + def releaseVersion = utils.getReleaseVersion() def emailSubject = "UpdateStableIdentifier and UpdateDOIs complete for v${releaseVersion}" def emailBody = "Hello,\n\nThis is an automated message from Jenkins regarding an update for v${releaseVersion}: Both UpdateStableIdentifiers and UpdateDOIs steps have completed. ${env.GK_CENTRAL_DB} can likely be reopened, but Curation should get \'Human\' confirmation before doing so. \n\nThanks!" utils.sendEmail("${emailSubject}", "${emailBody}") - } - } + } + } } } } diff --git a/checkstyle.xml b/checkstyle.xml index 8506a80..0a4c665 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -3,7 +3,7 @@ "https://checkstyle.org/dtds/configuration_1_3.dtd"> - + diff --git a/pom.xml b/pom.xml index 476e47b..4827b1f 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,11 @@ log4j-core 2.17.1 + + org.jcommander + jcommander + 1.83 + org.reactome.release release-common-lib @@ -118,7 +123,7 @@ jar-with-dependencies - update-dois.jar + update-dois package @@ -138,7 +143,7 @@ true - update-dois-verifier.jar + update-dois-verifier package diff --git a/src/main/java/org/reactome/release/updateDOIs/ReportTests.java b/src/main/java/org/reactome/release/updateDOIs/ReportTests.java index d15f254..d94fd22 100644 --- a/src/main/java/org/reactome/release/updateDOIs/ReportTests.java +++ b/src/main/java/org/reactome/release/updateDOIs/ReportTests.java @@ -19,21 +19,32 @@ public static boolean verifyDOIMatches( GKInstance trDOI, GKInstance gkDOI, Stri if (trDOI.getDBID().equals(gkDOI.getDBID()) && trDOI.getDisplayName().equals(gkDOI.getDisplayName())) { return true; } else if (trDOI.getDBID().equals(gkDOI.getDBID()) && !trDOI.getDisplayName().equals(gkDOI.getDisplayName())) { - warningsLog.warn("[" + newDOI + "] Display names do not match: [Test Reactome]: " + trDOI.getDisplayName() + " ~ [GK Central]: " + gkDOI.getDisplayName()); + warningsLog.warn("[" + newDOI + "] Display names do not match: [Test Reactome]: " + trDOI.getDisplayName() + + " ~ [GK Central]: " + gkDOI.getDisplayName()); return false; } else if (!trDOI.getDBID().equals(gkDOI.getDBID()) && trDOI.getDisplayName().equals(gkDOI.getDisplayName())) { - warningsLog.warn("[" + newDOI + "] DB IDs do not match: [Test Reactome]: " + trDOI.getDBID() + " ~ [GK Central]: " + gkDOI.getDBID()); + warningsLog.warn("[" + newDOI + "] DB IDs do not match: [Test Reactome]: " + trDOI.getDBID() + + " ~ [GK Central]: " + gkDOI.getDBID()); return false; } else { - warningsLog.warn("DB ID and display name do not match: [Test Reactome]: " + trDOI + " ~ [GK Central]: " + gkDOI); + warningsLog.warn("DB ID and display name do not match: [Test Reactome]: " + trDOI + " ~ [GK Central]: " + + gkDOI); return false; } } - public static void expectedUpdatesTests(Map> expectedUpdatedDOIs, List updated, List notUpdated, int expectedNumberOfUpdatedDOIs, String REACTOME_DOI_PREFIX) { - // Checking if provided list matched updated instances. Any that don't, it attempts to determine why they might not of been updated. - // This entails comparing the DB ID, display name and the stable ID version of the provided list (UpdateDOIs.report) with the actual updated instances + public static void expectedUpdatesTests( + Map> expectedUpdatedDOIs, + List updated, + List notUpdated, + int expectedNumberOfUpdatedDOIs, + String REACTOME_DOI_PREFIX + ) { + // Checking if provided list matched updated instances. Any that don't, it attempts to determine why they + // might not of been updated. + // This entails comparing the DB ID, display name and the stable ID version of the provided list + // (UpdateDOIs.report) with the actual updated instances if (notUpdated.size() > 0) { warningsLog.warn("Some DOIs from UpdateDOIs.report were not updated"); @@ -46,8 +57,10 @@ public static void expectedUpdatesTests(Map> expectedU String missedStableId = missedClean.split("\\.")[0]; String missedStableIdVersion = missedClean.split("\\.")[1]; int resolved = 0; - // Iterate through each of the DOI's provided in UpdateDOIs.report, trying to find a match for the DOI that wasn't updated. - // If it finds a match of either DB ID, stable ID version, or the display name, it will try to determine which of those 3 fields don't match. + // Iterate through each of the DOI's provided in UpdateDOIs.report, trying to find a match for the DOI + // that wasn't updated. + // If it finds a match of either DB ID, stable ID version, or the display name, it will try to + // determine which of those 3 fields don't match. // Once it finds the field that doesn't match, it logs it and then ends the current iteration. for (String key : expectedUpdatedDOIs.keySet()) { @@ -55,16 +68,19 @@ public static void expectedUpdatesTests(Map> expectedU { if (!expectedUpdatedDOIs.get(key).get("stableIdVersion").equals(missedStableIdVersion)) { - warningsLog.warn("[" + key + "] StableID 'version' in DB different from expected: [DB] " + missedDoi + "* ~ [Expected] " + key + "*"); + warningsLog.warn("[" + key + "] StableID 'version' in DB different from expected: [DB] " + + missedDoi + "* ~ [Expected] " + key + "*"); resolved++; continue; } else if (!expectedUpdatedDOIs.get(key).get("displayName").equals(missedName)) { - warningsLog.warn("[" + key + "] 'Display name' in DB different from expected: [DB] " + missedName + " ~ [Expected] " + expectedUpdatedDOIs.get(key).get("displayName")); + warningsLog.warn("[" + key + "] 'Display name' in DB different from expected: [DB] " + + missedName + " ~ [Expected] " + expectedUpdatedDOIs.get(key).get("displayName")); resolved++; continue; } } else if (expectedUpdatedDOIs.get(key).get("displayName").equals(missedName)) { - warningsLog.warn("[" + key + "] 'DB ID' from DB different from expected, but found matching display name: ~ [DB] " + missed + " [Expected] " + key + ":" + missedName); + warningsLog.warn("[" + key + "] 'DB ID' from DB different from expected, but found matching " + + "display name: ~ [DB] " + missed + " [Expected] " + key + ":" + missedName); resolved++; continue; } @@ -78,7 +94,8 @@ public static void expectedUpdatesTests(Map> expectedU { for (String unresolvedDOI : unresolvedDOIs) { - warningsLog.warn("[" + unresolvedDOI + "]" + "DOI does not match any DOIs expected to be updated -- Could not match display name or DB ID"); + warningsLog.warn("[" + unresolvedDOI + "]" + "DOI does not match any DOIs expected to be updated " + + "-- Could not match display name or DB ID"); } } } else if (expectedUpdatedDOIs.size() != 0 && expectedNumberOfUpdatedDOIs > expectedUpdatedDOIs.size()) { diff --git a/src/main/java/org/reactome/release/updateDOIs/UpdateDOIs.java b/src/main/java/org/reactome/release/updateDOIs/UpdateDOIs.java index 88e7187..909b82e 100644 --- a/src/main/java/org/reactome/release/updateDOIs/UpdateDOIs.java +++ b/src/main/java/org/reactome/release/updateDOIs/UpdateDOIs.java @@ -35,7 +35,8 @@ public static void setAdaptors(MySQLAdaptor adaptorTR, MySQLAdaptor adaptorGK) { } @SuppressWarnings("unchecked") - public static void findAndUpdateDOIs(long personId, Path pathToReport, int releaseNumber, boolean testMode) throws IOException { + public static void findAndUpdateDOIs(long personId, Path pathToReport, int releaseNumber, boolean testMode) + throws IOException { Path doisListFilepath = Paths.get("doisToBeUpdated-v" + releaseNumber + ".txt"); if (testMode) { @@ -61,14 +62,17 @@ public static void findAndUpdateDOIs(long personId, Path pathToReport, int relea expectedUpdatedDOIs = UpdateDOIs.getExpectedUpdatedDOIs(pathToReport.toString()); } if (expectedUpdatedDOIs.size() == 0) { - logger.warn("No DOIs listed in UpdateDOIs.report. Please add expected DOI and displayName to UpdateDOIs.report."); + logger.warn("No DOIs listed in UpdateDOIs.report. " + + "Please add expected DOI and displayName to UpdateDOIs.report."); } List updated = new ArrayList<>(); List notUpdated = new ArrayList<>(); try { - // Get all instances in Test Reactome in the Pathway table that don't have a 'doi' attribute starting with 10.3180, the Reactome DOI standard - doisTR = dbaTestReactome.fetchInstanceByAttribute(ReactomeJavaConstants.Pathway, "doi", "NOT REGEXP", "^" + REACTOME_DOI_PREFIX); + // Get all instances in Test Reactome in the Pathway table that don't have a 'doi' attribute starting + // with 10.3180, the Reactome DOI standard + doisTR = dbaTestReactome.fetchInstanceByAttribute( + ReactomeJavaConstants.Pathway, "doi", "NOT REGEXP", "^" + REACTOME_DOI_PREFIX); logger.info("Found " + doisTR.size() + " Pathway instances that need a DOI"); // GKCentral should require transactional support if (dbaGkCentral.supportsTransactions()) @@ -78,14 +82,17 @@ public static void findAndUpdateDOIs(long personId, Path pathToReport, int relea outerloop: for (GKInstance trDOI : doisTR) { - // The dois are constructed from the instances 'stableIdentifier', which should be in the db already - String stableIdFromDb = ((GKInstance) trDOI.getAttributeValue(ReactomeJavaConstants.stableIdentifier)).getDisplayName(); + // The dois are constructed from the instances 'stableIdentifier', + // which should be in the db already + String stableIdFromDb = ((GKInstance) + trDOI.getAttributeValue(ReactomeJavaConstants.stableIdentifier)).getDisplayName(); String nameFromDb = trDOI.getAttributeValue(ReactomeJavaConstants.name).toString(); String updatedDoi = REACTOME_DOI_PREFIX + "/" + stableIdFromDb; String dbId = trDOI.getAttributeValue(ReactomeJavaConstants.DB_ID).toString(); // Used to verify that report contents are as expected, based on provided list from curators - if (expectedUpdatedDOIs.get(updatedDoi) != null && expectedUpdatedDOIs.get(updatedDoi).get("displayName").equals(nameFromDb)) + if (expectedUpdatedDOIs.get(updatedDoi) != null && + expectedUpdatedDOIs.get(updatedDoi).get("displayName").equals(nameFromDb)) { updated.add(updatedDoi); } else { @@ -95,14 +102,16 @@ public static void findAndUpdateDOIs(long personId, Path pathToReport, int relea continue; } } - // This updates the 'modified' field for Pathways instances, keeping track of when changes happened for each instance + // This updates the 'modified' field for Pathways instances, keeping track of when changes + // happened for each instance trDOI.getAttributeValuesList(ReactomeJavaConstants.modified); trDOI.addAttributeValue(ReactomeJavaConstants.modified, instanceEditTR); trDOI.setAttributeValue("doi", updatedDoi); - // Grabs instance from GKCentral based on DB_ID taken from Test Reactome and updates it's DOI + // Grabs instance from GKCentral based on DB_ID taken from Test Reactome and updates its DOI dbaGkCentral.startTransaction(); - doisGK = dbaGkCentral.fetchInstanceByAttribute(ReactomeJavaConstants.Pathway, ReactomeJavaConstants.DB_ID, "=", dbId); + doisGK = dbaGkCentral.fetchInstanceByAttribute( + ReactomeJavaConstants.Pathway, ReactomeJavaConstants.DB_ID, "=", dbId); if (!doisGK.isEmpty()) { for (GKInstance gkDOI : doisGK) @@ -136,7 +145,8 @@ public static void findAndUpdateDOIs(long personId, Path pathToReport, int relea dbaTestReactome.updateInstanceAttribute(trDOI, "doi"); } } - ReportTests.expectedUpdatesTests(expectedUpdatedDOIs, updated, notUpdated, doisTR.size(), REACTOME_DOI_PREFIX); + ReportTests.expectedUpdatesTests( + expectedUpdatedDOIs, updated, notUpdated, doisTR.size(), REACTOME_DOI_PREFIX); } else { logger.info("No DOIs to update"); } @@ -177,7 +187,10 @@ public static Map> getExpectedUpdatedDOIs(String path String reactomeDoi = commaSplit[0]; String displayName = commaSplit[1]; int lastPeriodIndex = commaSplit[0].lastIndexOf("."); - String[] versionSplit = {reactomeDoi.substring(0, lastPeriodIndex), reactomeDoi.substring(lastPeriodIndex+1)}; + String[] versionSplit = { + reactomeDoi.substring(0, lastPeriodIndex), + reactomeDoi.substring(lastPeriodIndex + 1) + }; String stableId = versionSplit[0].replace(REACTOME_DOI_PREFIX + "/", ""); String stableIdVersion = versionSplit[1]; doiAttributes.put("displayName", displayName); @@ -233,8 +246,9 @@ public static GKInstance createInstanceEdit(MySQLAdaptor dbAdaptor, long personI * @return an InstanceEdit object. * @throws Exception */ - public static GKInstance createDefaultIE(MySQLAdaptor dba, Long defaultPersonId, boolean needStore, String note) - throws Exception { + public static GKInstance createDefaultIE( + MySQLAdaptor dba, Long defaultPersonId, boolean needStore, String note) throws Exception { + GKInstance defaultPerson = dba.fetchInstance(defaultPersonId); if (defaultPerson != null) { GKInstance newIE = UpdateDOIs.createDefaultInstanceEdit(defaultPerson); diff --git a/src/main/java/org/reactome/release/updateDOIs/Verifier.java b/src/main/java/org/reactome/release/updateDOIs/Verifier.java new file mode 100644 index 0000000..1e3899d --- /dev/null +++ b/src/main/java/org/reactome/release/updateDOIs/Verifier.java @@ -0,0 +1,245 @@ +package org.reactome.release.updateDOIs; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import org.gk.model.GKInstance; +import org.gk.model.ReactomeJavaConstants; +import org.gk.persistence.MySQLAdaptor; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.SQLException; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Joel Weiser (joel.weiser@oicr.on.ca) + * Created 11/26/2024 + */ +public class Verifier { + @Parameter(names ={"--releaseNumber", "--r"}, required = true) + private int releaseNumber; + + @Parameter(names ={"--curatorUser", "--cu"}, required = true) + private String curatorUserName; + + @Parameter(names ={"--curatorPassword", "--cp"}, required = true) + private String curatorPassword; + + @Parameter(names ={"--curatorHost", "--ch"}) + private String curatorHost = "localhost"; + + @Parameter(names ={"--curatorDbName", "--cd"}) + private String curatorDatabaseName = "gk_central"; + + @Parameter(names ={"--curatorPort", "--cP"}) + private int curatorPort = 3306; + + @Parameter(names ={"--releaseUser", "--ru"}, required = true) + private String releaseUserName; + + @Parameter(names ={"--releasePassword", "--rp"}, required = true) + private String releasePassword; + + @Parameter(names ={"--releaseHost", "--rh"}) + private String releaseHost = "localhost"; + + @Parameter(names ={"--releaseDbName", "--rd"}) + private String releaseDatabaseName = "release_current"; + + @Parameter(names ={"--releasePort", "--rP"}) + private int releasePort = 3306; + + + public static void main(String[] args) throws Exception { + Verifier verifier = new Verifier(); + JCommander.newBuilder() + .addObject(verifier) + .build() + .parse(args); + + verifier.run(); + } + + public void run() throws Exception { + List errorMessages = getErrorMessages(); + if (errorMessages.isEmpty()) { + System.out.println("Update DOIs has run correctly!"); + } else { + errorMessages.forEach(System.err::println); + System.exit(1); + } + } + + private List getErrorMessages() throws Exception { + List errorMessages = new ArrayList<>(); + + MySQLAdaptor curatorDBA = getCuratorDBA(); + MySQLAdaptor releaseDBA = getReleaseDBA(); + + errorMessages.addAll(checkReleaseDBAForPathwaysWithUnassignedDOIs(releaseDBA)); + errorMessages.addAll(checkCuratorDBAForPathwaysRequiringDOIs(curatorDBA)); + + for (MySQLAdaptor dba : Arrays.asList(curatorDBA, releaseDBA)) { + errorMessages.addAll(checkDBAForPathwaysWithUnexpectedDOIs(dba)); + } + + return errorMessages; + } + + private List checkReleaseDBAForPathwaysWithUnassignedDOIs(MySQLAdaptor releaseDBA) throws Exception { + List errorMessages = new ArrayList<>(); + + List releasedPathwaysNeedingDOIs = getPathwaysNeedingDOI(releaseDBA); + if (!releasedPathwaysNeedingDOIs.isEmpty()) { + errorMessages.add("The following pathways in the release database still require DOIs:"); + for (GKInstance releasedPathwayNeedingDOI : releasedPathwaysNeedingDOIs) { + errorMessages.add(releasedPathwayNeedingDOI.toString()); + } + } + + return errorMessages; + } + + private List checkCuratorDBAForPathwaysRequiringDOIs(MySQLAdaptor curatorDBA) throws Exception { + List errorMessages = new ArrayList<>(); + + List curatedPathwaysNeedingDOIs = getPathwaysNeedingDOI(curatorDBA); + if (!curatedPathwaysNeedingDOIs.isEmpty()) { + List curatedPathwaysExpectedToHaveDOIs = matchingExpectedDOIs(curatedPathwaysNeedingDOIs); + if (!curatedPathwaysExpectedToHaveDOIs.isEmpty()) { + errorMessages.add("The following pathways in the curated database still require DOIs:"); + for (GKInstance curatedPathwayExpectedToHaveDOI : curatedPathwaysExpectedToHaveDOIs) { + errorMessages.add(curatedPathwayExpectedToHaveDOI.toString()); + } + } + } + + return errorMessages; + } + + private List checkDBAForPathwaysWithUnexpectedDOIs(MySQLAdaptor dba) throws Exception { + List errorMessages = new ArrayList<>(); + + for (String expectedDOI : getExpectedDOIs()) { + GKInstance pathway = getPathwayByDOI(expectedDOI, dba); + if (!hasExpectedDOI(pathway, expectedDOI)) { + errorMessages.add(String.format("Pathway %s in %s database has '%s' as its doi (expected %s)", + pathway, dba.getDBName(), getCorrectDOI(pathway), expectedDOI)); + } + } + + return errorMessages; + } + + private List getPathwaysNeedingDOI(MySQLAdaptor dba) throws Exception { + return ((Collection) dba.fetchInstancesByClass(ReactomeJavaConstants.Pathway)) + .stream() + .filter(this::needsDOI) + .collect(Collectors.toList()); + } + + private List matchingExpectedDOIs(List pathwaysNeedingDOIs) throws IOException { + List pathwaysExpectedToHaveDOIs = new ArrayList<>(); + + List expectedDOIs = getExpectedDOIs(); + for (String expectedDOI : expectedDOIs) { + Optional pathwayExpectedToHaveDOI = + pathwaysNeedingDOIs.stream().filter(pathway -> getCorrectDOI(pathway).equals(expectedDOI)).findFirst(); + pathwayExpectedToHaveDOI.ifPresent(pathwaysExpectedToHaveDOIs::add); + } + return pathwaysExpectedToHaveDOIs; + } + + private GKInstance getPathwayByDOI(String doi, MySQLAdaptor dba) throws Exception { + Collection pathwaysWithDOI = + dba.fetchInstanceByAttribute(ReactomeJavaConstants.Pathway, ReactomeJavaConstants.doi, "=", doi); + if (pathwaysWithDOI.isEmpty()) { + throw new RuntimeException("Unable to find pathway with doi " + doi + " in database " + dba.getDBName()); + } + + if (pathwaysWithDOI.size() > 1) { + throw new RuntimeException("More than one pathway, " + pathwaysWithDOI + ", found with doi " + doi + + " in database " + dba.getDBName()); + } + + return pathwaysWithDOI.iterator().next(); + } + + private boolean hasExpectedDOI(GKInstance pathway, String expectedDOI) throws Exception { + String actualDOI = (String) pathway.getAttributeValue(ReactomeJavaConstants.doi); + return actualDOI.equals(expectedDOI); + } + + private String getCorrectDOI(GKInstance pathway) { + final String reactomeDOIPrefix = "10.3180/"; + + try { + GKInstance pathwayStableIdInstance = (GKInstance) + pathway.getAttributeValue(ReactomeJavaConstants.stableIdentifier); + String pathwayStableId = pathwayStableIdInstance.getDisplayName(); + + return reactomeDOIPrefix + pathwayStableId; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private boolean needsDOI(GKInstance pathway) { + String doiValue; + try { + doiValue = (String) pathway.getAttributeValue(ReactomeJavaConstants.doi); + } catch (Exception e) { + throw new RuntimeException("Unable to get doi value from pathway " + pathway, e); + } + return doiValue != null && doiValue.equals("needs DOI"); + } + + private List getExpectedDOIs() throws IOException { + return Files.lines(getExpectedDOIFile()) + .map(this::getDOIFromFileLine) + .collect(Collectors.toList()); + } + + private Path getExpectedDOIFile() { + return Paths.get(String.format("doisToBeUpdated-v%d.txt", this.releaseNumber)); + } + + private String getDOIFromFileLine(String line) { + return line.split(",")[0]; + } + + private MySQLAdaptor getCuratorDBA() throws SQLException { + return getDbAdaptor( + this.curatorHost, + this.curatorDatabaseName, + this.curatorUserName, + this.curatorPassword, + this.curatorPort + ); + } + + private MySQLAdaptor getReleaseDBA() throws SQLException { + return getDbAdaptor( + this.releaseHost, + this.releaseDatabaseName, + this.releaseUserName, + this.releasePassword, + this.releasePort + ); + } + + private MySQLAdaptor getDbAdaptor(String host, String dbName, String userName, String password, int port) + throws SQLException { + + return new MySQLAdaptor( + host, + dbName, + userName, + password, + port + ); + } +}