diff --git a/src/main/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommand.java b/src/main/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommand.java index 107e73e6..255b7d31 100644 --- a/src/main/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommand.java +++ b/src/main/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommand.java @@ -34,6 +34,7 @@ public void init() throws IOException { verifier.setHttpClient(httpClient); verifier.setProject(project); verifier.setShowProgress(true); + verifier.setChompbConfig(parentCommand.getChompbConfig()); } @Override @@ -47,7 +48,8 @@ public Integer call() throws Exception { outputLogger.info("Checked {} out of {} objects in the report", outcome.verifiedCount, outcome.totalRecords); if (outcome.hasErrors()) { - outputLogger.info("Errors encountered for {} objects, see report for details:", outcome.errorCount); + outputLogger.info("Boxc URL Errors encountered for {} objects, see report for details:", outcome.urlErrorCount); + outputLogger.info("Parent Collection Errors encountered for {} objects:", outcome.parentCollErrorCount); outputLogger.info(project.getPostMigrationReportPath().toString()); return 1; } diff --git a/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportService.java b/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportService.java index 7490e460..4f3e14d2 100644 --- a/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportService.java +++ b/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportService.java @@ -129,7 +129,7 @@ public void addWorkRow(String cdmObjectId, String boxcWorkId, int childCount, bo } addRow(cdmObjectId, cdmUrl, objType, boxcUrl, boxcTitle, matchingValue, sourceFile, - null, parentUrl, parentTitle, childCount); + null, parentUrl, parentTitle, childCount, null, null); } /** @@ -165,14 +165,14 @@ public void addFileRow(String fileCdmId, String parentCdmId, String boxcWorkId, } addRow(fileCdmId, cdmUrl, objType, boxcUrl, boxcTitle, matchingValue, sourceFile, - null, parentUrl, parentTitle, null); + null, parentUrl, parentTitle, null, null, null); } protected void addRow(String cdmId, String cdmUrl, String objType, String boxcUrl, String boxcTitle, String matchingValue, String sourceFile, String verified, String parentUrl, - String parentTitle, Integer childCount) throws IOException { + String parentTitle, Integer childCount, String parentCollUrl, String parentCollTitle) throws IOException { csvPrinter.printRecord(cdmId, cdmUrl, objType, boxcUrl, boxcTitle, matchingValue, sourceFile, - verified, parentUrl, parentTitle, childCount); + verified, parentUrl, parentTitle, childCount, parentCollUrl, parentCollTitle); } private String buildCdmUrl(String cdmObjectId, boolean isWorkObject, boolean isSingleItem) { diff --git a/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifier.java b/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifier.java index 22fe27d9..614b1f08 100644 --- a/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifier.java +++ b/src/main/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifier.java @@ -1,5 +1,6 @@ package edu.unc.lib.boxc.migration.cdm.services; +import com.fasterxml.jackson.databind.ObjectMapper; import edu.unc.lib.boxc.migration.cdm.exceptions.InvalidProjectStateException; import edu.unc.lib.boxc.migration.cdm.model.MigrationProject; import edu.unc.lib.boxc.migration.cdm.util.DisplayProgressUtil; @@ -7,17 +8,27 @@ import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.csv.CSVRecord; +import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; +import org.slf4j.Logger; import org.springframework.http.HttpStatus; import java.io.BufferedWriter; import java.io.IOException; import java.io.Reader; import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.HashMap; +import java.util.Map; + +import static edu.unc.lib.boxc.migration.cdm.util.PostMigrationReportConstants.API_PATH; +import static edu.unc.lib.boxc.migration.cdm.util.PostMigrationReportConstants.RECORD_PATH; +import static org.slf4j.LoggerFactory.getLogger; /** * Service which verifies the Box-c URLs in the post migration report and updates the verified field @@ -25,11 +36,13 @@ * @author bbpennel */ public class PostMigrationReportVerifier { + private static final Logger log = getLogger(PostMigrationReportVerifier.class); private MigrationProject project; private CloseableHttpClient httpClient; + private ChompbConfigService.ChompbConfig chompbConfig; private boolean showProgress; - public VerificationOutcome verify() throws IOException { + public VerificationOutcome verify() throws IOException, URISyntaxException { validateReport(); var outcome = new VerificationOutcome(); @@ -42,20 +55,30 @@ public VerificationOutcome verify() throws IOException { ) { long currentNum = 0; updateProgressDisplay(currentNum, totalRecords); + var baseUrl = chompbConfig.getBxcEnvironments().get(project.getProjectProperties().getBxcEnvironmentId()).getHttpBaseUrl(); for (CSVRecord originalRecord : csvParser) { var verified = originalRecord.get(PostMigrationReportConstants.VERIFIED_HEADER); - var rowValues = originalRecord.toList(); + var rowValuesMap = originalRecord.toMap(); + var boxcUrl = originalRecord.get(PostMigrationReportConstants.BXC_URL_HEADER); // 'verified' field is empty or was not previously successful, so request the boxc url if (!isStatusAcceptable(verified)) { - var boxcUrl = originalRecord.get(PostMigrationReportConstants.BXC_URL_HEADER); var result = requestHttpResult(boxcUrl); outcome.recordResult(result); - rowValues.set(PostMigrationReportConstants.VERIFIED_INDEX, result); + rowValuesMap.put(PostMigrationReportConstants.VERIFIED_HEADER, result); } + + // add parent collection information + var parentCollInfo = getParentCollectionInfo(boxcUrl, outcome, baseUrl + API_PATH); + var parentCollId = parentCollInfo.get("id"); + rowValuesMap.put(PostMigrationReportConstants.PARENT_COLL_URL_HEADER, + formatParentCollUrl(parentCollId, baseUrl + RECORD_PATH)); + rowValuesMap.put(PostMigrationReportConstants.PARENT_COLL_TITLE_HEADER, parentCollInfo.get("name")); + + // Write the row out into the new version of the report - csvPrinter.printRecord(rowValues); + csvPrinter.printRecord(rowValuesMap.values()); currentNum++; updateProgressDisplay(currentNum, totalRecords); @@ -92,6 +115,41 @@ private String requestHttpResult(String bxcUrl) throws IOException { } } + private Map getParentCollectionInfo(String bxcUrl, VerificationOutcome outcome, String bxcApiBaseUrl) throws IOException, URISyntaxException { + var map = new HashMap(); + var id = getId(bxcUrl); + var getRequest = new HttpGet(URI.create(bxcApiBaseUrl + id+ "/json")); + try (var resp = httpClient.execute(getRequest)) { + if (resp.getStatusLine().getStatusCode() != HttpStatus.OK.value()) { + map.put("id", ""); + map.put("name", ""); + outcome.recordParentCollError(); + return map; + } + var body = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8); + var mapper = new ObjectMapper(); + var jsonNode = mapper.readTree(body); + map.put("id", jsonNode.get("briefObject").get("parentCollectionId").asText()); + map.put("name", jsonNode.get("briefObject").get("parentCollectionName").asText()); + } + return map; + } + + private String getId(String url) throws URISyntaxException { + var uri = new URI(url); + String path = uri.getPath(); + + String[] parts = path.split("/"); + return parts[parts.length - 1]; + } + + private String formatParentCollUrl(String id, String bxcRecordBaseUrl) { + if (id.isBlank()) { + return ""; + } + return bxcRecordBaseUrl + id; + } + private CSVParser openCsvParser() throws IOException { Reader reader = Files.newBufferedReader(project.getPostMigrationReportPath()); return new CSVParser(reader, PostMigrationReportConstants.CSV_PARSER_FORMAT); @@ -135,24 +193,33 @@ public void setShowProgress(boolean showProgress) { this.showProgress = showProgress; } + public void setChompbConfig(ChompbConfigService.ChompbConfig chompbConfig) { + this.chompbConfig = chompbConfig; + } + private static boolean isStatusAcceptable(String status) { return HttpStatus.OK.name().equals(status) || HttpStatus.FORBIDDEN.name().equals(status); } public static class VerificationOutcome { - public long errorCount = 0; + public long urlErrorCount = 0; public long verifiedCount = 0; public long totalRecords = 0; + public long parentCollErrorCount = 0; protected void recordResult(String result) { if (!isStatusAcceptable(result)) { - errorCount++; + urlErrorCount++; } verifiedCount++; } + protected void recordParentCollError() { + parentCollErrorCount++; + } + public boolean hasErrors() { - return errorCount > 0; + return urlErrorCount > 0 || parentCollErrorCount > 0; } } } diff --git a/src/main/java/edu/unc/lib/boxc/migration/cdm/util/PostMigrationReportConstants.java b/src/main/java/edu/unc/lib/boxc/migration/cdm/util/PostMigrationReportConstants.java index 6d63ca4e..29a4ee89 100644 --- a/src/main/java/edu/unc/lib/boxc/migration/cdm/util/PostMigrationReportConstants.java +++ b/src/main/java/edu/unc/lib/boxc/migration/cdm/util/PostMigrationReportConstants.java @@ -10,18 +10,23 @@ public class PostMigrationReportConstants { public static final String BXC_URL_HEADER = "boxc_url"; public static final String VERIFIED_HEADER = "verified"; - public static final int VERIFIED_INDEX = 7; + public static final String PARENT_COLL_URL_HEADER = "parent_collection_url"; + public static final String PARENT_COLL_TITLE_HEADER = "parent_collection_title"; + public static final String RECORD_PATH = "record/"; + public static final String API_PATH = "api/" + RECORD_PATH; + public static final String[] CSV_HEADERS = new String[] { "cdm_id", "cdm_url", "boxc_obj_type", "boxc_url", "boxc_title", "matching_value", "source_file", - VERIFIED_HEADER, "boxc_parent_work_url", "boxc_parent_work_title", "children_count" }; + VERIFIED_HEADER, "boxc_parent_work_url", "boxc_parent_work_title", "children_count", PARENT_COLL_URL_HEADER, + PARENT_COLL_TITLE_HEADER }; public static final CSVFormat CSV_OUTPUT_FORMAT = CSVFormat.Builder.create() .setHeader(CSV_HEADERS) - .build(); + .get(); public static final CSVFormat CSV_PARSER_FORMAT = CSVFormat.Builder.create() .setSkipHeaderRecord(true) .setHeader(CSV_HEADERS) .setTrim(true) - .build(); + .get(); private PostMigrationReportConstants() { } diff --git a/src/test/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommandIT.java b/src/test/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommandIT.java index 0755243d..d05b8c07 100644 --- a/src/test/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommandIT.java +++ b/src/test/java/edu/unc/lib/boxc/migration/cdm/VerifyPostMigrationCommandIT.java @@ -9,12 +9,15 @@ import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static edu.unc.lib.boxc.migration.cdm.test.PostMigrationReportTestHelper.JSON; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -54,6 +57,10 @@ public void successTest() throws Exception { stubFor(get(urlMatching("/bxc/record/.*")) .willReturn(aResponse() .withStatus(HttpStatus.OK.value()))); + stubFor(get(urlMatching("/bxc/api/.*")) + .willReturn(aResponse() + .withBody(JSON) + .withStatus(HttpStatus.OK.value()))); generateSip(); @@ -72,6 +79,10 @@ public void errorsTest() throws Exception { stubFor(get(urlMatching("/bxc/record/.*")) .willReturn(aResponse() .withStatus(HttpStatus.NOT_FOUND.value()))); + stubFor(get(urlMatching("/bxc/api/.*")) + .willReturn(aResponse() + .withBody(JSON) + .withStatus(HttpStatus.OK.value()))); generateSip(); @@ -84,6 +95,26 @@ public void errorsTest() throws Exception { assertTrue(Files.readString(project.getPostMigrationReportPath()).contains(HttpStatus.NOT_FOUND.name())); } + @Test + public void parentCollectionErrorsTest() { + stubFor(get(urlMatching("/bxc/record/.*")) + .willReturn(aResponse() + .withStatus(HttpStatus.OK.value()))); + stubFor(get(urlMatching("/bxc/api/.*")) + .willReturn(aResponse() + .withBody(JSON) + .withStatus(HttpStatus.NOT_FOUND.value()))); + + generateSip(); + + String[] args = new String[] { + "-w", project.getProjectPath().toString(), + "verify_migration" }; + executeExpectFailure(args); + assertOutputContains("Parent Collection Errors encountered for 6 objects"); + assertTrue(Files.exists(project.getPostMigrationReportPath())); + } + private void generateSip() { var sipService = testHelper.createSipsService(); var sipOptions = new SipGenerationOptions(); diff --git a/src/test/java/edu/unc/lib/boxc/migration/cdm/services/MigrationTypeReportServiceTest.java b/src/test/java/edu/unc/lib/boxc/migration/cdm/services/MigrationTypeReportServiceTest.java index e8d020a0..33696577 100644 --- a/src/test/java/edu/unc/lib/boxc/migration/cdm/services/MigrationTypeReportServiceTest.java +++ b/src/test/java/edu/unc/lib/boxc/migration/cdm/services/MigrationTypeReportServiceTest.java @@ -51,9 +51,9 @@ public void setup() throws Exception { public void reportCountWorksTest() throws Exception { reportGenerator.init(); reportGenerator.addRow("25", CDM_URL_1, "Work", BOXC_URL_1, "Redoubt C", - null, null, null, "", "", 1); + null, null, null, "", "", 1, null, null); reportGenerator.addRow("26", CDM_URL_2, "File", BOXC_URL_2, "A file", - null, null, null, BOXC_URL_1, "Redoubt C", null); + null, null, null, BOXC_URL_1, "Redoubt C", null, null, null); reportGenerator.closeCsv(); long numWorks = service.countWorks(); @@ -64,11 +64,11 @@ public void reportCountWorksTest() throws Exception { public void reportCountFilesTest() throws Exception { reportGenerator.init(); reportGenerator.addRow("25", CDM_URL_1, "Work", BOXC_URL_1, "Redoubt C", - null, null, null, "", "", 1); + null, null, null, "", "", 1, null, null); reportGenerator.addRow("26", CDM_URL_2, "File", BOXC_URL_2, "A file", - null, null, null, BOXC_URL_1, "Redoubt C", null); + null, null, null, BOXC_URL_1, "Redoubt C", null, null, null); reportGenerator.addRow("27", CDM_URL_3, "File", BOXC_URL_3, "A file", - null, null, null, BOXC_URL_1, "Redoubt C", null); + null, null, null, BOXC_URL_1, "Redoubt C", null, null, null); reportGenerator.closeCsv(); long numFiles = service.countFiles(); diff --git a/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportServiceTest.java b/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportServiceTest.java index 5b748bb8..3e4bc6c0 100644 --- a/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportServiceTest.java +++ b/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportServiceTest.java @@ -87,7 +87,9 @@ public void addSingleItemTest() throws Exception { "", "", "", - "1"); + "1", + "", + ""); assertContainsRow(rows, "25/original_file", "http://localhost/cdm/singleitem/collection/proj/id/25", "File", @@ -98,6 +100,8 @@ public void addSingleItemTest() throws Exception { "", BOXC_URL_1, "Redoubt C", + "", + "", ""); } @@ -124,7 +128,9 @@ public void addSingleItemWithFileDescTest() throws Exception { "", "", "", - "1"); + "1", + "", + ""); assertContainsRow(rows, "25/original_file", "http://localhost/cdm/singleitem/collection/proj/id/25", "File", @@ -135,6 +141,8 @@ public void addSingleItemWithFileDescTest() throws Exception { "", BOXC_URL_1, "Redoubt C", + "", + "", ""); } @@ -163,7 +171,9 @@ public void addGroupedTest() throws Exception { "", "", "", - "2"); + "2", + "", + ""); assertContainsRow(rows, "26", "http://localhost/cdm/singleitem/collection/proj/id/26", "File", @@ -174,6 +184,8 @@ public void addGroupedTest() throws Exception { "", BOXC_URL_1, "Folder Group 1", + "", + "", ""); assertContainsRow(rows, "27", "http://localhost/cdm/singleitem/collection/proj/id/27", @@ -185,6 +197,8 @@ public void addGroupedTest() throws Exception { "", BOXC_URL_1, "Folder Group 1", + "", + "", ""); } @@ -214,7 +228,9 @@ public void addCompoundTest() throws Exception { "", "", "", - "2"); + "2", + "", + ""); assertContainsRow(rows, "602", "http://localhost/cdm/singleitem/collection/proj/id/602", "File", @@ -225,6 +241,8 @@ public void addCompoundTest() throws Exception { "", BOXC_URL_1, "Tiffany's pillbox commemorating UNC's bicentennial (closed, in box)", + "", + "", ""); assertContainsRow(rows, "603", "http://localhost/cdm/singleitem/collection/proj/id/603", @@ -236,6 +254,8 @@ public void addCompoundTest() throws Exception { "", BOXC_URL_1, "Tiffany's pillbox commemorating UNC's bicentennial (closed, in box)", + "", + "", ""); } diff --git a/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifierTest.java b/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifierTest.java index 2401b2e1..c31618dc 100644 --- a/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifierTest.java +++ b/src/test/java/edu/unc/lib/boxc/migration/cdm/services/PostMigrationReportVerifierTest.java @@ -5,6 +5,7 @@ import edu.unc.lib.boxc.migration.cdm.test.BxcEnvironmentHelper; import edu.unc.lib.boxc.migration.cdm.test.CdmEnvironmentHelper; import edu.unc.lib.boxc.migration.cdm.test.SipServiceHelper; +import org.apache.http.HttpEntity; import org.apache.http.StatusLine; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; @@ -18,13 +19,22 @@ import org.mockito.Mock; import org.springframework.http.HttpStatus; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; import java.util.Map; -import static edu.unc.lib.boxc.migration.cdm.test.PostMigrationReportTestHelper.assertContainsRow; +import static edu.unc.lib.boxc.migration.cdm.test.PostMigrationReportTestHelper.JSON; +import static edu.unc.lib.boxc.migration.cdm.test.PostMigrationReportTestHelper.PARENT_COLL_ID; +import static edu.unc.lib.boxc.migration.cdm.test.PostMigrationReportTestHelper.PARENT_COLL_TITLE; +import static edu.unc.lib.boxc.migration.cdm.test.PostMigrationReportTestHelper.PARENT_COLL_URL; import static edu.unc.lib.boxc.migration.cdm.test.PostMigrationReportTestHelper.parseReport; +import static edu.unc.lib.boxc.migration.cdm.util.PostMigrationReportConstants.API_PATH; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -43,6 +53,8 @@ public class PostMigrationReportVerifierTest { public Path tmpFolder; @Mock private CloseableHttpClient httpClient; + @Mock + private HttpEntity respEntity; private SipServiceHelper testHelper; private MigrationProject project; private PostMigrationReportService reportGenerator; @@ -61,6 +73,7 @@ public void setup() throws Exception { verifier = new PostMigrationReportVerifier(); verifier.setProject(project); verifier.setHttpClient(httpClient); + verifier.setChompbConfig(testHelper.getChompbConfig()); } @AfterEach @@ -69,7 +82,7 @@ void closeService() throws Exception { } @Test - public void noReportTest() throws Exception { + public void noReportTest() { Assertions.assertThrows(InvalidProjectStateException.class, () -> { verifier.verify(); }); @@ -78,22 +91,23 @@ public void noReportTest() throws Exception { @Test public void reportVerifySuccessTest() throws Exception { mockBxcResponses(Map.of(BOXC_URL_1, HttpStatus.OK, - BOXC_URL_2, HttpStatus.FORBIDDEN)); + BOXC_URL_2, HttpStatus.FORBIDDEN), false); reportGenerator.init(); reportGenerator.addRow("25", CDM_URL_1, "Work", BOXC_URL_1, "Redoubt C", - null, null, null, "", "", 1); + null, null, null, "", "", 1, null, null); reportGenerator.addRow("26", CDM_URL_2, "File", BOXC_URL_2, "A file", - null, null, null, BOXC_URL_1, "Redoubt C", null); + null, null, null, BOXC_URL_1, "Redoubt C", null, null, null); reportGenerator.closeCsv(); var outcome = verifier.verify(); assertEquals(2, outcome.verifiedCount); assertEquals(2, outcome.totalRecords); - assertEquals(0, outcome.errorCount); + assertEquals(0, outcome.urlErrorCount); + assertEquals(0, outcome.parentCollErrorCount); var rows = parseReport(project); - assertContainsRow(rows, "25", + assertRowContainsAllInfo(rows, "25", CDM_URL_1, "Work", BOXC_URL_1, @@ -103,8 +117,10 @@ public void reportVerifySuccessTest() throws Exception { HttpStatus.OK.name(), "", "", - "1"); - assertContainsRow(rows, "26", + "1", + PARENT_COLL_URL, + PARENT_COLL_TITLE); + assertRowContainsAllInfo(rows, "26", CDM_URL_2, "File", BOXC_URL_2, @@ -114,28 +130,31 @@ public void reportVerifySuccessTest() throws Exception { HttpStatus.OK.name(), BOXC_URL_1, "Redoubt C", - ""); + "", + PARENT_COLL_URL, + PARENT_COLL_TITLE); } @Test public void reportVerifyErrorsTest() throws Exception { mockBxcResponses(Map.of(BOXC_URL_1, HttpStatus.NOT_FOUND, - BOXC_URL_2, HttpStatus.NOT_FOUND)); + BOXC_URL_2, HttpStatus.NOT_FOUND), false); reportGenerator.init(); reportGenerator.addRow("25", CDM_URL_1, "Work", BOXC_URL_1, "Redoubt C", - null, null, null, "", "", 1); + null, null, null, "", "", 1, null, null); reportGenerator.addRow("26", CDM_URL_2, "File", BOXC_URL_2, "A file", - null, null, null, BOXC_URL_1, "Redoubt C", null); + null, null, null, BOXC_URL_1, "Redoubt C", null, null, null); reportGenerator.closeCsv(); var outcome = verifier.verify(); assertEquals(2, outcome.verifiedCount); assertEquals(2, outcome.totalRecords); - assertEquals(2, outcome.errorCount); + assertEquals(2, outcome.urlErrorCount); + assertEquals(0, outcome.parentCollErrorCount); var rows = parseReport(project); - assertContainsRow(rows, "25", + assertRowContainsAllInfo(rows, "25", CDM_URL_1, "Work", BOXC_URL_1, @@ -145,8 +164,10 @@ public void reportVerifyErrorsTest() throws Exception { HttpStatus.NOT_FOUND.name(), "", "", - "1"); - assertContainsRow(rows, "26", + "1", + PARENT_COLL_URL, + PARENT_COLL_TITLE); + assertRowContainsAllInfo(rows, "26", CDM_URL_2, "File", BOXC_URL_2, @@ -156,27 +177,30 @@ public void reportVerifyErrorsTest() throws Exception { HttpStatus.NOT_FOUND.name(), BOXC_URL_1, "Redoubt C", - ""); + "", + PARENT_COLL_URL, + PARENT_COLL_TITLE); } @Test public void reportVerifyPartialTest() throws Exception { - mockBxcResponses(Map.of(BOXC_URL_2, HttpStatus.OK)); + mockBxcResponses(Map.of(BOXC_URL_2, HttpStatus.OK), false); reportGenerator.init(); reportGenerator.addRow("25", CDM_URL_1, "Work", BOXC_URL_1, "Redoubt C", - null, null, HttpStatus.OK.name(), "", "", 1); + null, null, HttpStatus.OK.name(), "", "", 1, null, null); reportGenerator.addRow("26", CDM_URL_2, "File", BOXC_URL_2, "A file", - null, null, null, BOXC_URL_1, "Redoubt C", null); + null, null, null, BOXC_URL_1, "Redoubt C", null, null, null); reportGenerator.closeCsv(); var outcome = verifier.verify(); assertEquals(1, outcome.verifiedCount); assertEquals(2, outcome.totalRecords); - assertEquals(0, outcome.errorCount); + assertEquals(0, outcome.urlErrorCount); + assertEquals(0, outcome.parentCollErrorCount); var rows = parseReport(project); - assertContainsRow(rows, "25", + assertRowContainsAllInfo(rows, "25", CDM_URL_1, "Work", BOXC_URL_1, @@ -186,8 +210,10 @@ public void reportVerifyPartialTest() throws Exception { HttpStatus.OK.name(), "", "", - "1"); - assertContainsRow(rows, "26", + "1", + PARENT_COLL_URL, + PARENT_COLL_TITLE); + assertRowContainsAllInfo(rows, "26", CDM_URL_2, "File", BOXC_URL_2, @@ -197,17 +223,87 @@ public void reportVerifyPartialTest() throws Exception { HttpStatus.OK.name(), BOXC_URL_1, "Redoubt C", + "", + PARENT_COLL_URL, + PARENT_COLL_TITLE); + } + + @Test + public void reportVerifyWithParentCollectionError() throws Exception { + mockBxcResponses(Map.of(BOXC_URL_1, HttpStatus.OK, BOXC_URL_2, HttpStatus.OK), true); + + reportGenerator.init(); + reportGenerator.addRow("25", CDM_URL_1, "Work", BOXC_URL_1, "Redoubt C", + null, null, null, "", "", 1, null, null); + reportGenerator.addRow("26", CDM_URL_2, "File", BOXC_URL_2, "A file", + null, null, null, BOXC_URL_1, "Redoubt C", null, null, null); + reportGenerator.closeCsv(); + + var outcome = verifier.verify(); + assertEquals(2, outcome.verifiedCount); + assertEquals(2, outcome.totalRecords); + assertEquals(0, outcome.urlErrorCount); + assertEquals(2, outcome.parentCollErrorCount); + + var rows = parseReport(project); + assertRowContainsAllInfo(rows, "25", + CDM_URL_1, + "Work", + BOXC_URL_1, + "Redoubt C", + "", + "", + HttpStatus.OK.name(), + "", + "", + "1", + "", + ""); + assertRowContainsAllInfo(rows, "26", + CDM_URL_2, + "File", + BOXC_URL_2, + "A file", + "", + "", + HttpStatus.OK.name(), + BOXC_URL_1, + "Redoubt C", + "", + "", ""); } - private void mockBxcResponses(Map urlToStatus) throws IOException { + private void mockBxcResponses(Map urlToStatus, boolean apiFailure) throws IOException { when(httpClient.execute(any(HttpUriRequest.class))).thenAnswer(invocation -> { HttpGet httpGet = invocation.getArgument(0); - var resp1 = mock(CloseableHttpResponse.class); - var statusLine1 = mock(StatusLine.class); - when(resp1.getStatusLine()).thenReturn(statusLine1); - when(statusLine1.getStatusCode()).thenReturn(urlToStatus.get(httpGet.getURI().toString()).value()); - return resp1; + var requestUrl = httpGet.getURI().toString(); + var resp = mock(CloseableHttpResponse.class); + when(resp.getEntity()).thenReturn(respEntity); + var statusLine = mock(StatusLine.class); + when(resp.getStatusLine()).thenReturn(statusLine); + + if (requestUrl.contains(API_PATH)) { + if (apiFailure) { + when(statusLine.getStatusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR.value()); + return resp; + } + when(statusLine.getStatusCode()).thenReturn(HttpStatus.OK.value()); + when(respEntity.getContent()).thenReturn(new ByteArrayInputStream(JSON.getBytes(StandardCharsets.UTF_8))); + } else { + when(statusLine.getStatusCode()).thenReturn(urlToStatus.get(httpGet.getURI().toString()).value()); + } + return resp; }); } + + public static void assertRowContainsAllInfo(List> rows, String cdmId, String cdmUrl, String objType, + String bxcUrl, String bxcTitle, String matchingValue, String sourceFile, + String verified, String parentUrl, String parentTitle, String childCount, + String parentCollUrl, String parentCollTitle) { + var found = rows.stream().filter(r -> r.getFirst().equals(cdmId)).findFirst().orElse(null); + assertNotNull(found, "Did not find row for CDM id " + cdmId + ", rows were:\n" + rows); + assertEquals(Arrays.asList(cdmId, cdmUrl, objType, bxcUrl, bxcTitle, matchingValue, sourceFile, verified, + parentUrl, parentTitle, childCount, parentCollUrl, parentCollTitle), found); + } } diff --git a/src/test/java/edu/unc/lib/boxc/migration/cdm/test/PostMigrationReportTestHelper.java b/src/test/java/edu/unc/lib/boxc/migration/cdm/test/PostMigrationReportTestHelper.java index 18819dd1..6638dac8 100644 --- a/src/test/java/edu/unc/lib/boxc/migration/cdm/test/PostMigrationReportTestHelper.java +++ b/src/test/java/edu/unc/lib/boxc/migration/cdm/test/PostMigrationReportTestHelper.java @@ -11,6 +11,8 @@ import java.util.Arrays; import java.util.List; +import static edu.unc.lib.boxc.migration.cdm.test.BxcEnvironmentHelper.TEST_BASE_URL; +import static edu.unc.lib.boxc.migration.cdm.util.PostMigrationReportConstants.RECORD_PATH; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -20,6 +22,17 @@ public class PostMigrationReportTestHelper { private PostMigrationReportTestHelper() { } + public static final String PARENT_COLL_ID = "4fe5080f-41cd-4b1e-9cdd-71203c824cd0"; + public static final String PARENT_COLL_URL = TEST_BASE_URL + RECORD_PATH + PARENT_COLL_ID; + public static final String PARENT_COLL_TITLE = "Latin Studies Program"; + public static final String JSON = "{\"findingAidUrl\":\"https://finding-aids.lib.unc.edu/catalog/40489\"," + + "\"viewerType\":\"clover\",\"canBulkDownload\":false,\"dataFileUrl\":\"content/6f4b5e38-754f-49ca-a4a0-6441fea95d76\"," + + "\"markedForDeletion\":false,\"pageSubtitle\":\"TEST.jpg\",\"briefObject\":{\"added\":\"2018-05-24T20:39:18.165Z\"," + + "\"counts\":{\"child\":1},\"created\":\"2018-05-24T20:39:18.165Z\",\"format\":[\"Image\"],\"parentCollectionName\":\"" + PARENT_COLL_TITLE +"\"," + + "\"contentStatus\":[\"Not Described\",\"Has Primary Object\"],\"rollup\":\"1a1e9c1a-cdd2-4874-b6cb-8da783919460\"," + + "\"parentCollectionId\":\"" + PARENT_COLL_ID + "\",\"id\":\"1a1e9c1a-cdd2-4874-b6cb-8da783919460\"," + + "\"updated\":\"2018-05-25T13:37:01.864Z\",\"fileType\":[\"image/jpeg\"],\"status\":[\"Public Access\"],\"timestamp\":1751312648385}," + + "\"collectionId\":\"40489\",\"resourceType\":\"Work\"}"; public static List> parseReport(MigrationProject project) throws Exception { try ( @@ -53,10 +66,11 @@ public static void assertContainsRow(List> rows, String cdmId, Stri // Assert row matches all provided fields public static void assertContainsRow(List> rows, String cdmId, String cdmUrl, String objType, String bxcUrl, String bxcTitle, String matchingValue, String sourceFile, - String verified, String parentUrl, String parentTitle, String childCount) { + String verified, String parentUrl, String parentTitle, String childCount, + String parentCollUrl, String parentCollTitle) { var found = rows.stream().filter(r -> r.get(0).equals(cdmId)).findFirst().orElse(null); assertNotNull(found, "Did not find row for CDM id " + cdmId + ", rows were:\n" + rows); assertEquals(Arrays.asList(cdmId, cdmUrl, objType, bxcUrl, bxcTitle, matchingValue, sourceFile, verified, - parentUrl, parentTitle, childCount), found); + parentUrl, parentTitle, childCount, parentCollUrl, parentCollTitle), found); } }