From 4cd5d567d128fd3cd09d5ffe38ba5be8e342016d Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Mon, 18 Dec 2017 16:32:37 -0600 Subject: [PATCH 01/10] Endpoint 3 without database changes. --- .../controllers/v1/CpcFileControllerV1.java | 12 ++++++ .../api/services/CpcFileService.java | 8 ++++ .../api/services/CpcFileServiceImpl.java | 30 ++++++++++++++- .../v1/CpcFileControllerV1Test.java | 12 ++++++ .../api/services/CpcFileServiceImplTest.java | 37 +++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java index a1d5da062..f9975e79e 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java @@ -72,4 +72,16 @@ public ResponseEntity getFileById(@PathVariable("fileId") S return new ResponseEntity<>(content, httpHeaders, HttpStatus.OK); } + + @RequestMapping(method = RequestMethod.POST, value = "/mark-file/{fileId}", + headers = {"Accept=" + Constants.V1_API_ACCEPT} ) + public ResponseEntity markFileProcessed(@PathVariable("fileId") String fileId) { + API_LOG.info("CPC+ file request received"); + String message = cpcFileService.processFileById(fileId); + API_LOG.info("CPC+ file request succeeded"); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.TEXT_PLAIN); + + return new ResponseEntity<>(message, httpHeaders, HttpStatus.OK); + } } diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileService.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileService.java index 7f12e7bc4..955a8698d 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileService.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileService.java @@ -25,4 +25,12 @@ public interface CpcFileService { * @throws IOException for invalid IOUtils usage */ InputStreamResource getFileById(String fileId) throws IOException; + + /** + * Marks a CPC File as processed by id + * + * @param fileId Identifier of the CPC+ file + * @return Success or failure message + */ + String processFileById(String fileId); } diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java index 57ce882f3..8c8fb3fe6 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java @@ -17,6 +17,7 @@ public class CpcFileServiceImpl implements CpcFileService { public static final String FILE_NOT_FOUND = "File not found!"; + protected static final String FILE_FOUND = "The file was found and will be updated as processed."; @Autowired private DbService dbService; @@ -45,13 +46,30 @@ public List getUnprocessedCpcPlusFiles() { */ public InputStreamResource getFileById(String fileId) throws IOException { Metadata metadata = dbService.getMetadataById(fileId); - if (metadata != null && metadata.getCpc() && !metadata.getCpcProcessed()) { + if (isAnUnprocessedCpcFile(metadata)) { return new InputStreamResource(storageService.getFileByLocationId(metadata.getSubmissionLocator())); } else { throw new NoFileInDatabaseException(FILE_NOT_FOUND); } } + /** + * Process to ensure the file is an unprocessed cpc+ file and marks the file as processed + * + * @param fileId Identifier of the CPC+ file + * @return Success or failure message. + */ + public String processFileById(String fileId) { + Metadata metadata = dbService.getMetadataById(fileId); + if (isAnUnprocessedCpcFile(metadata)) { + metadata.setCpcProcessed(true); + dbService.write(metadata); + return FILE_FOUND; + } else { + throw new NoFileInDatabaseException(FILE_NOT_FOUND); + } + } + /** * Service to transform a {@link Metadata} list into the {@link UnprocessedCpcFileData} * @@ -61,4 +79,14 @@ public InputStreamResource getFileById(String fileId) throws IOException { private List transformMetaDataToUnprocessedCpcFileData(List metadataList) { return metadataList.stream().map(UnprocessedCpcFileData::new).collect(Collectors.toList()); } + + /** + * Determines if the file is unprocessed and is CPC+ + * + * @param metadata Data to be determined valid or invalid + * @return result of the check + */ + private boolean isAnUnprocessedCpcFile(Metadata metadata) { + return metadata != null && metadata.getCpc() && !metadata.getCpcProcessed(); + } } diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java index b9849ff35..6e64af6b8 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -62,6 +63,17 @@ void testGetFileById() throws IOException { .isEqualTo("1234"); } + @Test + void testMarkFileAsProcessed() { + when(cpcFileService.processFileById(anyString())).thenReturn("success!"); + + ResponseEntity response = cpcFileControllerV1.markFileProcessed("meep"); + + verify(cpcFileService, times(1)).processFileById(anyString()); + + assertThat(response.getBody()).isEqualTo("success!"); + } + List createMockedUnprocessedDataList() { Metadata metadata = new Metadata(); metadata.setSubmissionLocator("Test"); diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java index b7884a9cf..7f9362549 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java @@ -28,6 +28,8 @@ @ExtendWith(MockitoExtension.class) class CpcFileServiceImplTest { + private static final String MEEP = "meep"; + @InjectMocks private CpcFileServiceImpl objectUnderTest; @@ -104,6 +106,41 @@ void testGetFileByIdNoFile() throws IOException { assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.FILE_NOT_FOUND); } + @Test + void testProcessFileByIdSuccess() { + when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(true, false)); + + String message = objectUnderTest.processFileById(MEEP); + + verify(dbService, times(1)).getMetadataById(anyString()); + + assertThat(message).isEqualTo(CpcFileServiceImpl.FILE_FOUND); + } + + @Test + void testProcessFileByIdWithMipsFile() { + when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(false, false)); + + NoFileInDatabaseException expectedException = assertThrows(NoFileInDatabaseException.class, () + -> objectUnderTest.processFileById("test")); + + verify(dbService, times(1)).getMetadataById(anyString()); + + assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.FILE_NOT_FOUND); + } + + @Test + void testProcessFileByIdWithProcessedFile() { + when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(true, true)); + + NoFileInDatabaseException expectedException = assertThrows(NoFileInDatabaseException.class, () + -> objectUnderTest.processFileById("test")); + + verify(dbService, times(1)).getMetadataById(anyString()); + + assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.FILE_NOT_FOUND); + } + Metadata buildFakeMetadata(boolean isCpc, boolean isCpcProcessed) { Metadata metadata = new Metadata(); metadata.setCpc(isCpc); From 1dbb9e1b710f081fe8f4869fc9e430b94a677a7c Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Tue, 19 Dec 2017 12:59:36 -0600 Subject: [PATCH 02/10] changing mark-file to file as a post --- .../qpp/conversion/api/controllers/v1/CpcFileControllerV1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java index 4b16d8897..92e59f427 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java @@ -73,7 +73,7 @@ public ResponseEntity getFileById(@PathVariable("fileId") S return new ResponseEntity<>(content, httpHeaders, HttpStatus.OK); } - @RequestMapping(method = RequestMethod.POST, value = "/mark-file/{fileId}", + @RequestMapping(method = RequestMethod.POST, value = "/file/{fileId}", headers = {"Accept=" + Constants.V1_API_ACCEPT} ) public ResponseEntity markFileProcessed(@PathVariable("fileId") String fileId) { API_LOG.info("CPC+ file request received"); From 2c7c50e30fc6bc7f21d84be8d22b9f7c7b7bc1ea Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Tue, 19 Dec 2017 16:57:14 -0600 Subject: [PATCH 03/10] Fixes from PR comments --- .../api/controllers/v1/CpcFileControllerV1.java | 14 ++++++++++---- .../api/services/CpcFileServiceImpl.java | 4 +++- .../controllers/v1/CpcFileControllerV1Test.java | 16 ++++++++++++++-- .../api/services/CpcFileServiceImplTest.java | 9 +++++++-- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java index 92e59f427..0d7b150b9 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java @@ -61,11 +61,11 @@ public ResponseEntity getUnprocessedCpcPlusFiles() throws IOException { headers = {"Accept=" + Constants.V1_API_ACCEPT}) public ResponseEntity getFileById(@PathVariable("fileId") String fileId) throws IOException { - API_LOG.info("CPC+ file request received"); + API_LOG.info("CPC+ file retrieval request received"); InputStreamResource content = cpcFileService.getFileById(fileId); - API_LOG.info("CPC+ file request succeeded"); + API_LOG.info("CPC+ file retrieval request succeeded"); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_XML); @@ -73,12 +73,18 @@ public ResponseEntity getFileById(@PathVariable("fileId") S return new ResponseEntity<>(content, httpHeaders, HttpStatus.OK); } + /** + * Updates a file's status to processed in the database + * + * @param fileId Identifier of the file needing to be updated + * @return Message if the file was updated or not + */ @RequestMapping(method = RequestMethod.POST, value = "/file/{fileId}", headers = {"Accept=" + Constants.V1_API_ACCEPT} ) public ResponseEntity markFileProcessed(@PathVariable("fileId") String fileId) { - API_LOG.info("CPC+ file request received"); + API_LOG.info("CPC+ update file as processed request received"); String message = cpcFileService.processFileById(fileId); - API_LOG.info("CPC+ file request succeeded"); + API_LOG.info("CPC+ update file as processed request succeeded"); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.TEXT_PLAIN); diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java index 8c8fb3fe6..2c1db49e7 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java @@ -5,6 +5,7 @@ import gov.cms.qpp.conversion.api.model.UnprocessedCpcFileData; import java.io.IOException; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; @@ -63,7 +64,8 @@ public String processFileById(String fileId) { Metadata metadata = dbService.getMetadataById(fileId); if (isAnUnprocessedCpcFile(metadata)) { metadata.setCpcProcessed(true); - dbService.write(metadata); + CompletableFuture metadataFuture = dbService.write(metadata); + metadataFuture.join(); return FILE_FOUND; } else { throw new NoFileInDatabaseException(FILE_NOT_FOUND); diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java index 6e64af6b8..91c4b0ecd 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1Test.java @@ -17,6 +17,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.core.io.InputStreamResource; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import static com.google.common.truth.Truth.assertThat; @@ -64,16 +65,27 @@ void testGetFileById() throws IOException { } @Test - void testMarkFileAsProcessed() { + void testMarkFileAsProcessedReturnsSuccess() { when(cpcFileService.processFileById(anyString())).thenReturn("success!"); ResponseEntity response = cpcFileControllerV1.markFileProcessed("meep"); - verify(cpcFileService, times(1)).processFileById(anyString()); + verify(cpcFileService, times(1)).processFileById("meep"); assertThat(response.getBody()).isEqualTo("success!"); } + @Test + void testMarkFileAsProcessedHttpStatusOk() { + when(cpcFileService.processFileById(anyString())).thenReturn("success!"); + + ResponseEntity response = cpcFileControllerV1.markFileProcessed("meep"); + + verify(cpcFileService, times(1)).processFileById("meep"); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + List createMockedUnprocessedDataList() { Metadata metadata = new Metadata(); metadata.setSubmissionLocator("Test"); diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java index 7f9362549..8e3e88989 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.io.IOUtils; @@ -20,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -108,11 +110,14 @@ void testGetFileByIdNoFile() throws IOException { @Test void testProcessFileByIdSuccess() { - when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(true, false)); + Metadata returnedData = buildFakeMetadata(true, false); + when(dbService.getMetadataById(anyString())).thenReturn(returnedData); + when(dbService.write(any(Metadata.class))).thenReturn(CompletableFuture.completedFuture(returnedData)); String message = objectUnderTest.processFileById(MEEP); - verify(dbService, times(1)).getMetadataById(anyString()); + verify(dbService, times(1)).getMetadataById(MEEP); + verify(dbService, times(1)).write(returnedData); assertThat(message).isEqualTo(CpcFileServiceImpl.FILE_FOUND); } From b02eeaa18ade608ae3c6f104fa6796ef1f79109e Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Thu, 21 Dec 2017 11:23:17 -0600 Subject: [PATCH 04/10] Change Marking MIPS files to throw InvalidFileTypeException - Change marking a Processed CPC+ file to return a message saying it is already processed. QPPCT-503 --- .../v1/ExceptionHandlerControllerV1.java | 18 +++++++++ .../exceptions/InvalidFileTypeException.java | 15 +++++++ .../api/services/CpcFileServiceImpl.java | 13 +++++-- .../v1/ExceptionHandlerControllerV1Test.java | 39 +++++++++++++++++-- .../InvalidFileTypeExceptionTest.java | 16 ++++++++ .../exceptions/NoFileInDatabaseException.java | 16 ++++++++ .../api/services/CpcFileServiceImplTest.java | 22 ++++++++--- 7 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java create mode 100644 rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeExceptionTest.java create mode 100644 rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/NoFileInDatabaseException.java diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java index d4ca8ca73..84596448a 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java @@ -1,5 +1,6 @@ package gov.cms.qpp.conversion.api.controllers.v1; +import gov.cms.qpp.conversion.api.exceptions.InvalidFileTypeException; import gov.cms.qpp.conversion.api.exceptions.NoFileInDatabaseException; import gov.cms.qpp.conversion.api.model.Constants; import gov.cms.qpp.conversion.api.services.AuditService; @@ -74,6 +75,23 @@ ResponseEntity handleFileNotFoundException(NoFileInDatabaseException exc return new ResponseEntity<>(exception.getMessage(), httpHeaders, HttpStatus.NOT_FOUND); } + + /** + * "Catch" the {@link NoFileInDatabaseException}. + * Return the {@link AllErrors} with an HTTP status 422. + * + * @param exception The NoFileInDatabaseException that was "caught". + * @return The NoFileInDatabaseException message + */ + @ExceptionHandler(InvalidFileTypeException.class) + @ResponseBody + ResponseEntity handleInvalidFileTypeException(InvalidFileTypeException exception) { + API_LOG.error("A file type error occurred", exception); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.TEXT_PLAIN); + + return new ResponseEntity<>(exception.getMessage(), httpHeaders, HttpStatus.NOT_FOUND); + } private ResponseEntity cope(TransformException exception) { HttpHeaders httpHeaders = new HttpHeaders(); diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java new file mode 100644 index 000000000..38b998323 --- /dev/null +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java @@ -0,0 +1,15 @@ +package gov.cms.qpp.conversion.api.exceptions; + +/** + * Exception for handling an invalid file type + */ +public class InvalidFileTypeException extends RuntimeException { + + /** + * Constructor to call RuntimeException + * @param message + */ + public InvalidFileTypeException(String message) { + super(message); + } +} diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java index 2c1db49e7..a62f8f98e 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java @@ -1,5 +1,6 @@ package gov.cms.qpp.conversion.api.services; +import gov.cms.qpp.conversion.api.exceptions.InvalidFileTypeException; import gov.cms.qpp.conversion.api.exceptions.NoFileInDatabaseException; import gov.cms.qpp.conversion.api.model.Metadata; import gov.cms.qpp.conversion.api.model.UnprocessedCpcFileData; @@ -18,6 +19,8 @@ public class CpcFileServiceImpl implements CpcFileService { public static final String FILE_NOT_FOUND = "File not found!"; + protected static final String INVALID_FILE = "The file was not a CPC+ file."; + protected static final String PROCESSED = "The file was already processed"; protected static final String FILE_FOUND = "The file was found and will be updated as processed."; @Autowired @@ -62,13 +65,17 @@ public InputStreamResource getFileById(String fileId) throws IOException { */ public String processFileById(String fileId) { Metadata metadata = dbService.getMetadataById(fileId); - if (isAnUnprocessedCpcFile(metadata)) { + if (metadata == null) { + throw new NoFileInDatabaseException(FILE_NOT_FOUND); + } else if (!metadata.getCpc()) { + throw new InvalidFileTypeException(INVALID_FILE); + } else if (metadata.getCpcProcessed()) { + return PROCESSED; + } else { metadata.setCpcProcessed(true); CompletableFuture metadataFuture = dbService.write(metadata); metadataFuture.join(); return FILE_FOUND; - } else { - throw new NoFileInDatabaseException(FILE_NOT_FOUND); } } diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1Test.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1Test.java index d3006589e..58058ef29 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1Test.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1Test.java @@ -1,6 +1,7 @@ package gov.cms.qpp.conversion.api.controllers.v1; import gov.cms.qpp.conversion.Converter; +import gov.cms.qpp.conversion.api.exceptions.InvalidFileTypeException; import gov.cms.qpp.conversion.api.exceptions.NoFileInDatabaseException; import gov.cms.qpp.conversion.PathSource; import gov.cms.qpp.conversion.api.services.AuditService; @@ -117,7 +118,7 @@ public void testQppValidationExceptionBody() { } @Test - public void testFileNotFoundExceptionStatusCode() { + public void testNoFileInDatabaseExceptionStatusCode() { NoFileInDatabaseException exception = new NoFileInDatabaseException(CpcFileServiceImpl.FILE_NOT_FOUND); @@ -129,7 +130,7 @@ public void testFileNotFoundExceptionStatusCode() { } @Test - public void testFileNotFoundExceptionHeaderContentType() { + public void testNoFileInDatabaseExceptionHeaderContentType() { NoFileInDatabaseException exception = new NoFileInDatabaseException(CpcFileServiceImpl.FILE_NOT_FOUND); @@ -140,11 +141,43 @@ public void testFileNotFoundExceptionHeaderContentType() { } @Test - public void testFileNotFoundExceptionBody() { + public void testNoFileInDatabaseExceptionBody() { NoFileInDatabaseException exception = new NoFileInDatabaseException(CpcFileServiceImpl.FILE_NOT_FOUND); ResponseEntity responseEntity = objectUnderTest.handleFileNotFoundException(exception); assertThat(responseEntity.getBody()).isEqualTo(CpcFileServiceImpl.FILE_NOT_FOUND); } + + @Test + public void testInvalidFileTypeExceptionStatusCode() { + InvalidFileTypeException exception = + new InvalidFileTypeException(CpcFileServiceImpl.FILE_NOT_FOUND); + + ResponseEntity responseEntity = objectUnderTest.handleInvalidFileTypeException(exception); + + assertWithMessage("The response entity's status code must be 422.") + .that(responseEntity.getStatusCode()) + .isEquivalentAccordingToCompareTo(HttpStatus.NOT_FOUND); + } + + @Test + public void testInvalidFileTypeExceptionHeaderContentType() { + InvalidFileTypeException exception = + new InvalidFileTypeException(CpcFileServiceImpl.FILE_NOT_FOUND); + + ResponseEntity responseEntity = objectUnderTest.handleInvalidFileTypeException(exception); + + assertThat(responseEntity.getHeaders().getContentType()) + .isEquivalentAccordingToCompareTo(MediaType.TEXT_PLAIN); + } + + @Test + public void testInvalidFileTypeExceptionBody() { + InvalidFileTypeException exception = + new InvalidFileTypeException(CpcFileServiceImpl.FILE_NOT_FOUND); + + ResponseEntity responseEntity = objectUnderTest.handleInvalidFileTypeException(exception); + assertThat(responseEntity.getBody()).isEqualTo(CpcFileServiceImpl.FILE_NOT_FOUND); + } } \ No newline at end of file diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeExceptionTest.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeExceptionTest.java new file mode 100644 index 000000000..abf86b6d5 --- /dev/null +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeExceptionTest.java @@ -0,0 +1,16 @@ +package gov.cms.qpp.conversion.api.exceptions; + +import org.junit.jupiter.api.Test; + +import static com.google.common.truth.Truth.assertThat; + +class InvalidFileTypeExceptionTest { + + @Test + void testConstructor() { + InvalidFileTypeException invalidFileTypeException = new InvalidFileTypeException("test"); + + + assertThat(invalidFileTypeException).hasMessageThat().isEqualTo("test"); + } +} diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/NoFileInDatabaseException.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/NoFileInDatabaseException.java new file mode 100644 index 000000000..ef7ee5993 --- /dev/null +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/exceptions/NoFileInDatabaseException.java @@ -0,0 +1,16 @@ +package gov.cms.qpp.conversion.api.exceptions; + +import org.junit.jupiter.api.Test; + +import static com.google.common.truth.Truth.assertThat; + +class NoFileInDatabaseExceptionTest { + + @Test + void testConstructor() { + NoFileInDatabaseException noFileInDatabaseException = new NoFileInDatabaseException("test"); + + + assertThat(noFileInDatabaseException).hasMessageThat().isEqualTo("test"); + } +} diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java index 8e3e88989..7c29af5fb 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java @@ -1,5 +1,6 @@ package gov.cms.qpp.conversion.api.services; +import gov.cms.qpp.conversion.api.exceptions.InvalidFileTypeException; import gov.cms.qpp.conversion.api.exceptions.NoFileInDatabaseException; import gov.cms.qpp.conversion.api.model.Metadata; import gov.cms.qpp.test.MockitoExtension; @@ -123,8 +124,8 @@ void testProcessFileByIdSuccess() { } @Test - void testProcessFileByIdWithMipsFile() { - when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(false, false)); + void testProcessFileByIdFileNotFound() { + when(dbService.getMetadataById(anyString())).thenReturn(null); NoFileInDatabaseException expectedException = assertThrows(NoFileInDatabaseException.class, () -> objectUnderTest.processFileById("test")); @@ -134,16 +135,27 @@ void testProcessFileByIdWithMipsFile() { assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.FILE_NOT_FOUND); } + @Test + void testProcessFileByIdWithMipsFile() { + when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(false, false)); + + InvalidFileTypeException expectedException = assertThrows(InvalidFileTypeException.class, () + -> objectUnderTest.processFileById("test")); + + verify(dbService, times(1)).getMetadataById(anyString()); + + assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.INVALID_FILE); + } + @Test void testProcessFileByIdWithProcessedFile() { when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(true, true)); - NoFileInDatabaseException expectedException = assertThrows(NoFileInDatabaseException.class, () - -> objectUnderTest.processFileById("test")); + String response = objectUnderTest.processFileById("test"); verify(dbService, times(1)).getMetadataById(anyString()); - assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.FILE_NOT_FOUND); + assertThat(response).isEqualTo(CpcFileServiceImpl.PROCESSED); } Metadata buildFakeMetadata(boolean isCpc, boolean isCpcProcessed) { From e77a78299dd440e182101a63d29f50db9db799db Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Fri, 22 Dec 2017 08:34:10 -0600 Subject: [PATCH 05/10] Address most PR comments and sonar issue --- .../controllers/v1/ExceptionHandlerControllerV1.java | 10 +++++----- .../api/exceptions/InvalidFileTypeException.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java index 84596448a..353db775a 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/ExceptionHandlerControllerV1.java @@ -61,7 +61,7 @@ ResponseEntity handleQppValidationException(QppValidationException ex /** * "Catch" the {@link NoFileInDatabaseException}. - * Return the {@link AllErrors} with an HTTP status 422. + * Return the {@link AllErrors} with an HTTP status 404. * * @param exception The NoFileInDatabaseException that was "caught". * @return The NoFileInDatabaseException message @@ -77,11 +77,11 @@ ResponseEntity handleFileNotFoundException(NoFileInDatabaseException exc } /** - * "Catch" the {@link NoFileInDatabaseException}. - * Return the {@link AllErrors} with an HTTP status 422. + * "Catch" the {@link InvalidFileTypeException}. + * Return the {@link AllErrors} with an HTTP status 404. * - * @param exception The NoFileInDatabaseException that was "caught". - * @return The NoFileInDatabaseException message + * @param exception The InvalidFileTypeException that was "caught". + * @return The InvalidFileTypeException message */ @ExceptionHandler(InvalidFileTypeException.class) @ResponseBody diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java index 38b998323..d3b999ed0 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/exceptions/InvalidFileTypeException.java @@ -7,7 +7,7 @@ public class InvalidFileTypeException extends RuntimeException { /** * Constructor to call RuntimeException - * @param message + * @param message Error response */ public InvalidFileTypeException(String message) { super(message); From bf66f6313b8f0f56bab6ef6874d8b2a35e4cd81e Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Fri, 22 Dec 2017 10:27:44 -0600 Subject: [PATCH 06/10] Changing as a PUT request and removing the extra messaging --- .../api/controllers/v1/CpcFileControllerV1.java | 2 +- .../conversion/api/services/CpcFileServiceImpl.java | 3 --- .../api/services/CpcFileServiceImplTest.java | 11 ----------- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java index 229f823fd..1f89fbd1c 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java @@ -91,7 +91,7 @@ public ResponseEntity getFileById(@PathVariable("fileId") S * @param fileId Identifier of the file needing to be updated * @return Message if the file was updated or not */ - @RequestMapping(method = RequestMethod.POST, value = "/file/{fileId}", + @RequestMapping(method = RequestMethod.PUT, value = "/file/{fileId}", headers = {"Accept=" + Constants.V1_API_ACCEPT} ) public ResponseEntity markFileProcessed(@PathVariable("fileId") String fileId) { if (blockCpcPlusApi()) { diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java index a62f8f98e..74fa66e05 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java @@ -20,7 +20,6 @@ public class CpcFileServiceImpl implements CpcFileService { public static final String FILE_NOT_FOUND = "File not found!"; protected static final String INVALID_FILE = "The file was not a CPC+ file."; - protected static final String PROCESSED = "The file was already processed"; protected static final String FILE_FOUND = "The file was found and will be updated as processed."; @Autowired @@ -69,8 +68,6 @@ public String processFileById(String fileId) { throw new NoFileInDatabaseException(FILE_NOT_FOUND); } else if (!metadata.getCpc()) { throw new InvalidFileTypeException(INVALID_FILE); - } else if (metadata.getCpcProcessed()) { - return PROCESSED; } else { metadata.setCpcProcessed(true); CompletableFuture metadataFuture = dbService.write(metadata); diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java index 7c29af5fb..1a1466327 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java @@ -147,17 +147,6 @@ void testProcessFileByIdWithMipsFile() { assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.INVALID_FILE); } - @Test - void testProcessFileByIdWithProcessedFile() { - when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(true, true)); - - String response = objectUnderTest.processFileById("test"); - - verify(dbService, times(1)).getMetadataById(anyString()); - - assertThat(response).isEqualTo(CpcFileServiceImpl.PROCESSED); - } - Metadata buildFakeMetadata(boolean isCpc, boolean isCpcProcessed) { Metadata metadata = new Metadata(); metadata.setCpc(isCpc); From 57f08ae6b76f438d7a9ce711d89797a285739fe7 Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Fri, 22 Dec 2017 10:31:32 -0600 Subject: [PATCH 07/10] Remove the need to write to the database --- .../cms/qpp/conversion/api/services/CpcFileServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java index 74fa66e05..8c43ebe9a 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java @@ -20,6 +20,7 @@ public class CpcFileServiceImpl implements CpcFileService { public static final String FILE_NOT_FOUND = "File not found!"; protected static final String INVALID_FILE = "The file was not a CPC+ file."; + protected static final String PROCESSED = "The file was already processed"; protected static final String FILE_FOUND = "The file was found and will be updated as processed."; @Autowired @@ -68,6 +69,8 @@ public String processFileById(String fileId) { throw new NoFileInDatabaseException(FILE_NOT_FOUND); } else if (!metadata.getCpc()) { throw new InvalidFileTypeException(INVALID_FILE); + } else if (metadata.getCpcProcessed()) { + return FILE_FOUND; } else { metadata.setCpcProcessed(true); CompletableFuture metadataFuture = dbService.write(metadata); From e4a2861fbd03f1d884b6e7314f9e15cb951654af Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Fri, 22 Dec 2017 10:32:25 -0600 Subject: [PATCH 08/10] Add the test back in --- .../api/services/CpcFileServiceImplTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java index 1a1466327..bfa9f01df 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImplTest.java @@ -147,6 +147,17 @@ void testProcessFileByIdWithMipsFile() { assertThat(expectedException).hasMessageThat().isEqualTo(CpcFileServiceImpl.INVALID_FILE); } + @Test + void testProcessFileByIdWithProcessedFile() { + when(dbService.getMetadataById(anyString())).thenReturn(buildFakeMetadata(true, true)); + + String response = objectUnderTest.processFileById("test"); + + verify(dbService, times(1)).getMetadataById(anyString()); + + assertThat(response).isEqualTo(CpcFileServiceImpl.FILE_FOUND); + } + Metadata buildFakeMetadata(boolean isCpc, boolean isCpcProcessed) { Metadata metadata = new Metadata(); metadata.setCpc(isCpc); From 4052696cf1d1c32dd0747318ebab16054c14488e Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Fri, 22 Dec 2017 10:34:30 -0600 Subject: [PATCH 09/10] Remove PROCESSED static string --- .../gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java index 8c43ebe9a..87e30b283 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/services/CpcFileServiceImpl.java @@ -20,7 +20,6 @@ public class CpcFileServiceImpl implements CpcFileService { public static final String FILE_NOT_FOUND = "File not found!"; protected static final String INVALID_FILE = "The file was not a CPC+ file."; - protected static final String PROCESSED = "The file was already processed"; protected static final String FILE_FOUND = "The file was found and will be updated as processed."; @Autowired From 400ac83d906afb8d24ca6fd8900076d69868ae4e Mon Sep 17 00:00:00 2001 From: Samuel Aquino Date: Fri, 22 Dec 2017 16:53:32 -0600 Subject: [PATCH 10/10] Add CrossOrigin --- .../qpp/conversion/api/controllers/v1/CpcFileControllerV1.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java index 30a12d60f..f76225222 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/v1/CpcFileControllerV1.java @@ -13,6 +13,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -26,6 +27,7 @@ */ @RestController @RequestMapping("/cpc") +@CrossOrigin public class CpcFileControllerV1 { private static final Logger API_LOG = LoggerFactory.getLogger(Constants.API_LOG);