Skip to content

Commit

Permalink
DMP-4141 (Dev Only) ARM RPO - Integrate downloadProduction (#2253)
Browse files Browse the repository at this point in the history
  • Loading branch information
karen-hedges authored Nov 12, 2024
1 parent 5c0f772 commit a05f8ef
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package uk.gov.hmcts.darts.arm.rpo;

import feign.FeignException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import uk.gov.hmcts.darts.arm.client.ArmRpoClient;
import uk.gov.hmcts.darts.arm.exception.ArmRpoException;
import uk.gov.hmcts.darts.common.entity.ArmRpoExecutionDetailEntity;
import uk.gov.hmcts.darts.common.entity.UserAccountEntity;
import uk.gov.hmcts.darts.common.enums.ArmRpoStateEnum;
import uk.gov.hmcts.darts.common.enums.ArmRpoStatusEnum;
import uk.gov.hmcts.darts.testutils.IntegrationBase;

import java.io.IOException;
import java.io.InputStream;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@SuppressWarnings("PMD.CloseResource")
class ArmRpoApiDownloadProductionIntTest extends IntegrationBase {

@MockBean
private ArmRpoClient armRpoClient;

@Autowired
private ArmRpoApi armRpoApi;


@Test
void downloadProductionSuccess() throws IOException {
// given
feign.Response response = mock(feign.Response.class);
when(response.status()).thenReturn(200);
InputStream inputStream = mock(InputStream.class);
feign.Response.Body body = mock(feign.Response.Body.class);
when(response.body()).thenReturn(body);
when(body.asInputStream()).thenReturn(inputStream);
when(armRpoClient.downloadProduction(anyString(), anyString())).thenReturn(response);

UserAccountEntity userAccount = dartsDatabase.getUserAccountStub().getIntegrationTestUserAccountEntity();
ArmRpoExecutionDetailEntity armRpoExecutionDetailEntity = new ArmRpoExecutionDetailEntity();
armRpoExecutionDetailEntity.setCreatedBy(userAccount);
armRpoExecutionDetailEntity.setLastModifiedBy(userAccount);
var armRpoExecutionDetail = dartsPersistence.save(armRpoExecutionDetailEntity);


// when
try (InputStream result =
armRpoApi.downloadProduction("token", armRpoExecutionDetailEntity.getId(), "productionExportId", userAccount)) {
// then
assertNotNull(result);
}

// then
var armRpoExecutionDetailEntityUpdated = dartsPersistence.getArmRpoExecutionDetailRepository().findById(armRpoExecutionDetail.getId()).get();
assertEquals(ArmRpoStateEnum.DOWNLOAD_PRODUCTION.getId(), armRpoExecutionDetailEntityUpdated.getArmRpoState().getId());
assertEquals(ArmRpoStatusEnum.COMPLETED.getId(), armRpoExecutionDetailEntityUpdated.getArmRpoStatus().getId());

}

@Test
void downloadProductionThrowsFeignException() {
// given
when(armRpoClient.downloadProduction(anyString(), anyString())).thenThrow(FeignException.class);

UserAccountEntity userAccount = dartsDatabase.getUserAccountStub().getIntegrationTestUserAccountEntity();
ArmRpoExecutionDetailEntity armRpoExecutionDetailEntity = new ArmRpoExecutionDetailEntity();
armRpoExecutionDetailEntity.setCreatedBy(userAccount);
armRpoExecutionDetailEntity.setLastModifiedBy(userAccount);
var armRpoExecutionDetail = dartsPersistence.save(armRpoExecutionDetailEntity);

// when
ArmRpoException armRpoException = assertThrows(ArmRpoException.class, () ->
armRpoApi.downloadProduction("token", armRpoExecutionDetailEntity.getId(), "productionExportId", userAccount));


// then
assertThat(armRpoException.getMessage(), containsString(
"Failure during download production: Error during ARM RPO download production id: productionExportId"));

var armRpoExecutionDetailEntityUpdated = dartsPersistence.getArmRpoExecutionDetailRepository().findById(armRpoExecutionDetail.getId()).get();
assertEquals(ArmRpoStateEnum.DOWNLOAD_PRODUCTION.getId(), armRpoExecutionDetailEntityUpdated.getArmRpoState().getId());
assertEquals(ArmRpoStatusEnum.FAILED.getId(), armRpoExecutionDetailEntityUpdated.getArmRpoStatus().getId());

}
}
12 changes: 12 additions & 0 deletions src/main/java/uk/gov/hmcts/darts/arm/client/ArmRpoClient.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package uk.gov.hmcts.darts.arm.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
Expand All @@ -26,6 +28,7 @@

import static org.springframework.http.HttpHeaders.AUTHORIZATION;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;

@FeignClient(
name = "arm-rpo-client",
Expand All @@ -47,6 +50,7 @@ public interface ArmRpoClient {
StorageAccountResponse getStorageAccounts(@RequestHeader(AUTHORIZATION) String bearerToken,
@RequestBody StorageAccountRequest storageAccountRequest);


@PostMapping(value = "${darts.storage.arm-api.rpo-url.get-master-index-field-by-record-class-schema-path}",
consumes = APPLICATION_JSON_VALUE,
produces = APPLICATION_JSON_VALUE
Expand Down Expand Up @@ -115,4 +119,12 @@ RemoveProductionResponse removeProduction(@RequestHeader(AUTHORIZATION) String b
)
ExtendedProductionsByMatterResponse getExtendedProductionsByMatter(@RequestHeader(AUTHORIZATION) String bearerToken,
@RequestBody String body);

@GetMapping(value = "${darts.storage.arm-api.rpo-url.download-production-path}",
produces = APPLICATION_OCTET_STREAM_VALUE)
@SuppressWarnings({"PMD.UseObjectForClearerAPI"})
feign.Response downloadProduction(@RequestHeader(AUTHORIZATION) String bearerAuth,
@PathVariable("productionExportFileID") String productionExportFileId);


}
3 changes: 2 additions & 1 deletion src/main/java/uk/gov/hmcts/darts/arm/rpo/ArmRpoApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import uk.gov.hmcts.darts.common.entity.ArmRpoStateEntity;
import uk.gov.hmcts.darts.common.entity.UserAccountEntity;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

Expand Down Expand Up @@ -35,7 +36,7 @@ boolean createExportBasedOnSearchResultsTable(String bearerToken, Integer execut

List<String> getProductionOutputFiles(String bearerToken, Integer executionId, UserAccountEntity userAccount);

InputStream downloadProduction(String bearerToken, Integer executionId, String productionExportFileID, UserAccountEntity userAccount);
InputStream downloadProduction(String bearerToken, Integer executionId, String productionExportFileId, UserAccountEntity userAccount) throws IOException;

void removeProduction(String bearerToken, Integer executionId, UserAccountEntity userAccount);
}
123 changes: 75 additions & 48 deletions src/main/java/uk/gov/hmcts/darts/arm/rpo/impl/ArmRpoApiImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -45,6 +44,7 @@
import uk.gov.hmcts.darts.common.helper.CurrentTimeHelper;
import uk.gov.hmcts.darts.common.repository.ArmAutomatedTaskRepository;

import java.io.IOException;
import java.io.InputStream;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
Expand Down Expand Up @@ -92,7 +92,7 @@ public void getRecordManagementMatter(String bearerToken, Integer executionId, U
handleResponseStatus(userAccount, recordManagementMatterResponse, errorMessage, armRpoExecutionDetailEntity);

if (isNull(recordManagementMatterResponse.getRecordManagementMatter())
|| isNull(recordManagementMatterResponse.getRecordManagementMatter().getMatterId())) {
|| StringUtils.isBlank(recordManagementMatterResponse.getRecordManagementMatter().getMatterId())) {
throw handleFailureAndCreateException(ARM_GET_RECORD_MANAGEMENT_MATTER_ERROR, armRpoExecutionDetailEntity, userAccount);
}

Expand Down Expand Up @@ -120,7 +120,8 @@ public void getIndexesByMatterId(String bearerToken, Integer executionId, String

if (CollectionUtils.isEmpty(indexesByMatterIdResponse.getIndexes())
|| isNull(indexesByMatterIdResponse.getIndexes().getFirst())
|| isNull(indexesByMatterIdResponse.getIndexes().getFirst().getIndex())) {
|| isNull(indexesByMatterIdResponse.getIndexes().getFirst().getIndex())
|| StringUtils.isBlank(indexesByMatterIdResponse.getIndexes().getFirst().getIndex().getIndexId())) {
throw handleFailureAndCreateException(errorMessage.append("Unable to find indexes by matter ID in response").toString(),
armRpoExecutionDetailEntity,
userAccount);
Expand Down Expand Up @@ -171,7 +172,7 @@ public void getStorageAccounts(String bearerToken, Integer executionId, UserAcco
break;
}
}
if (!nonNull(storageAccountName)) {
if (StringUtils.isBlank(storageAccountName)) {
throw handleFailureAndCreateException(errorMessage.append("Unable to find ARM RPO storage account in response").toString(),
armRpoExecutionDetailEntity, userAccount);

Expand Down Expand Up @@ -272,7 +273,7 @@ public List<MasterIndexFieldByRecordClassSchema> getMasterIndexFieldByRecordClas
masterIndexFieldByRecordClassSchemaList.add(createMasterIndexFieldByRecordClassSchema(masterIndexField));
}
}
if (isNull(sortingField)) {
if (StringUtils.isBlank(sortingField)) {
throw handleFailureAndCreateException(errorMessage.append("Unable to find sorting field in response").toString(),
armRpoExecutionDetailEntity, userAccount);
}
Expand Down Expand Up @@ -461,45 +462,6 @@ public boolean createExportBasedOnSearchResultsTable(String bearerToken, Integer
return true;
}

private CreateExportBasedOnSearchResultsTableRequest createRequestForCreateExportBasedOnSearchResultsTable(
List<MasterIndexFieldByRecordClassSchemaResponse> headerColumns, String searchId, int searchItemsCount, String productionName,
String storageAccountId) {

return CreateExportBasedOnSearchResultsTableRequest.builder()
.core(null)
.formFields(null)
.searchId(searchId)
.searchitemsCount(searchItemsCount)
.headerColumns(createHeaderColumnsFromMasterIndexFieldByRecordClassSchemaResponse(headerColumns))
.productionName(productionName)
.storageAccountId(storageAccountId)
.build();
}

private List<CreateExportBasedOnSearchResultsTableRequest.HeaderColumn> createHeaderColumnsFromMasterIndexFieldByRecordClassSchemaResponse(
List<MasterIndexFieldByRecordClassSchemaResponse> masterIndexFieldByRecordClassSchemaResponses) {

List<CreateExportBasedOnSearchResultsTableRequest.HeaderColumn> headerColumnList = new ArrayList<>();
for (MasterIndexFieldByRecordClassSchemaResponse response : masterIndexFieldByRecordClassSchemaResponses) {
for (MasterIndexFieldByRecordClassSchemaResponse.MasterIndexField masterIndexField : response.getMasterIndexFields()) {
headerColumnList.add(createHeaderColumn(masterIndexField));
}
}
return headerColumnList;
}

private CreateExportBasedOnSearchResultsTableRequest.HeaderColumn createHeaderColumn(
MasterIndexFieldByRecordClassSchemaResponse.MasterIndexField masterIndexField) {
return CreateExportBasedOnSearchResultsTableRequest.HeaderColumn.builder()
.masterIndexField(masterIndexField.getMasterIndexFieldId())
.displayName(masterIndexField.getDisplayName())
.propertyName(masterIndexField.getPropertyName())
.propertyType(masterIndexField.getPropertyType())
.isMasked(masterIndexField.getIsMasked())
.build();
}


@Override
public void getExtendedProductionsByMatter(String bearerToken, Integer executionId, UserAccountEntity userAccount) {
var armRpoExecutionDetailEntity = armRpoService.getArmRpoExecutionDetailEntity(executionId);
Expand Down Expand Up @@ -570,7 +532,7 @@ public List<String> getProductionOutputFiles(String bearerToken, Integer executi
List<ProductionOutputFilesResponse.ProductionExportFile> productionExportFiles = response.getProductionExportFiles();
if (CollectionUtils.isEmpty(productionExportFiles)) {
throw handleFailureAndCreateException(exceptionMessageBuilder.append("No production export files were returned")
.toString(),
.toString(),
executionDetail, userAccount);
}

Expand All @@ -584,7 +546,7 @@ public List<String> getProductionOutputFiles(String bearerToken, Integer executi

if (productionExportFileIds.isEmpty()) {
throw handleFailureAndCreateException(exceptionMessageBuilder.append("No production export file ids were returned")
.toString(),
.toString(),
executionDetail, userAccount);
}

Expand All @@ -594,8 +556,35 @@ public List<String> getProductionOutputFiles(String bearerToken, Integer executi
}

@Override
public InputStream downloadProduction(String bearerToken, Integer executionId, String productionExportFileID, UserAccountEntity userAccount) {
throw new NotImplementedException("Method not implemented");
public InputStream downloadProduction(String bearerToken, Integer executionId, String productionExportFileId,
UserAccountEntity userAccount) throws IOException {
var armRpoExecutionDetailEntity = armRpoService.getArmRpoExecutionDetailEntity(executionId);
armRpoService.updateArmRpoStateAndStatus(armRpoExecutionDetailEntity, ArmRpoHelper.downloadProductionRpoState(),
ArmRpoHelper.inProgressRpoStatus(), userAccount);

feign.Response response;
StringBuilder errorMessage = new StringBuilder("Failure during download production: ");

try {
response = armRpoClient.downloadProduction(bearerToken, productionExportFileId);
} catch (FeignException e) {
// this ensures the full error body containing the ARM error detail is logged rather than a truncated version
log.error(errorMessage.append("Error during ARM RPO download production id: ").append(productionExportFileId)
.toString() + " {}", e.contentUTF8());
throw handleFailureAndCreateException(errorMessage.toString(), armRpoExecutionDetailEntity, userAccount);
}

// on any error occurring return a download failure
if (!HttpStatus.valueOf(response.status()).is2xxSuccessful()) {
errorMessage.append("Failed ARM RPO download production with id: ").append(productionExportFileId)
.append(" response ").append(response);
log.error(response.toString());
throw handleFailureAndCreateException(errorMessage.toString(), armRpoExecutionDetailEntity, userAccount);
}

log.debug("Successfully downloaded ARM data for productionExportFileId: {}", productionExportFileId);
armRpoService.updateArmRpoStatus(armRpoExecutionDetailEntity, ArmRpoHelper.completedRpoStatus(), userAccount);
return response.body().asInputStream();
}

@Override
Expand Down Expand Up @@ -706,6 +695,21 @@ private AddAsyncSearchRequestGenerator createAddAsyncSearchRequestGenerator(Stri
.build();
}

private CreateExportBasedOnSearchResultsTableRequest createRequestForCreateExportBasedOnSearchResultsTable(
List<MasterIndexFieldByRecordClassSchemaResponse> headerColumns, String searchId, int searchItemsCount, String productionName,
String storageAccountId) {

return CreateExportBasedOnSearchResultsTableRequest.builder()
.core(null)
.formFields(null)
.searchId(searchId)
.searchitemsCount(searchItemsCount)
.headerColumns(createHeaderColumnsFromMasterIndexFieldByRecordClassSchemaResponse(headerColumns))
.productionName(productionName)
.storageAccountId(storageAccountId)
.build();
}

private SaveBackgroundSearchRequest createSaveBackgroundSearchRequest(String searchName, String searchId) {
return SaveBackgroundSearchRequest.builder()
.name(searchName)
Expand All @@ -719,6 +723,29 @@ private GetExtendedSearchesByMatterRequestGenerator createExtendedSearchesByMatt
.build();
}

private List<CreateExportBasedOnSearchResultsTableRequest.HeaderColumn> createHeaderColumnsFromMasterIndexFieldByRecordClassSchemaResponse(
List<MasterIndexFieldByRecordClassSchemaResponse> masterIndexFieldByRecordClassSchemaResponses) {

List<CreateExportBasedOnSearchResultsTableRequest.HeaderColumn> headerColumnList = new ArrayList<>();
for (MasterIndexFieldByRecordClassSchemaResponse response : masterIndexFieldByRecordClassSchemaResponses) {
for (MasterIndexFieldByRecordClassSchemaResponse.MasterIndexField masterIndexField : response.getMasterIndexFields()) {
headerColumnList.add(createHeaderColumn(masterIndexField));
}
}
return headerColumnList;
}

private CreateExportBasedOnSearchResultsTableRequest.HeaderColumn createHeaderColumn(
MasterIndexFieldByRecordClassSchemaResponse.MasterIndexField masterIndexField) {
return CreateExportBasedOnSearchResultsTableRequest.HeaderColumn.builder()
.masterIndexField(masterIndexField.getMasterIndexFieldId())
.displayName(masterIndexField.getDisplayName())
.propertyName(masterIndexField.getPropertyName())
.propertyType(masterIndexField.getPropertyType())
.isMasked(masterIndexField.getIsMasked())
.build();
}

private ProductionOutputFilesRequest createProductionOutputFilesRequest(String productionId) {
return ProductionOutputFilesRequest.builder()
.productionId(productionId)
Expand Down
Loading

0 comments on commit a05f8ef

Please sign in to comment.