From e11c409ca6723490491ac57682b5284233e02cba Mon Sep 17 00:00:00 2001 From: Luis Pabon Date: Wed, 17 Jul 2024 12:22:02 -0400 Subject: [PATCH 1/6] Update Hl7FhirMappingPath.java Remove unused getter to increase coverage percentage --- .../trustedintermediary/plugin/path/Hl7FhirMappingPath.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/plugin/path/Hl7FhirMappingPath.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/plugin/path/Hl7FhirMappingPath.java index 371c089dc..833e7ab5d 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/plugin/path/Hl7FhirMappingPath.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/plugin/path/Hl7FhirMappingPath.java @@ -101,10 +101,6 @@ public enum Hl7FhirMappingPath { this.fhirPath = fhirPath; } - public String getHl7Path() { - return hl7Path; - } - public String getFhirPath() { return fhirPath; } From 419ee347af5ced7470bb24eec7ef3eae47c36982 Mon Sep 17 00:00:00 2001 From: Luis Pabon Date: Wed, 17 Jul 2024 12:31:50 -0400 Subject: [PATCH 2/6] Update DomainConnector.java Add @throws definition to remove warning --- .../trustedintermediary/domainconnector/DomainConnector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/main/java/gov/hhs/cdc/trustedintermediary/domainconnector/DomainConnector.java b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/domainconnector/DomainConnector.java index 43e3feebd..d58432f5b 100644 --- a/shared/src/main/java/gov/hhs/cdc/trustedintermediary/domainconnector/DomainConnector.java +++ b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/domainconnector/DomainConnector.java @@ -28,7 +28,7 @@ public interface DomainConnector { * An implementation would return the OpenAPI specification in YAML format for this domain * * @return The OpenAPI specifications for just this given domain - * @throws UnableToReadOpenApiSpecificationException + * @throws UnableToReadOpenApiSpecificationException When unable to load the expected file */ String openApiSpecification() throws UnableToReadOpenApiSpecificationException; } From e2f70d1596d01616e62353b9806b4779917f8428 Mon Sep 17 00:00:00 2001 From: Luis Pabon Date: Wed, 17 Jul 2024 14:18:35 -0400 Subject: [PATCH 3/6] Added OpenApiReader interface and implementation --- .../openapi/OpenApiReaderImplementation.java | 39 +++++++++++++++++++ .../wrappers/OpenApiReader.java | 8 ++++ 2 files changed, 47 insertions(+) create mode 100644 shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/openapi/OpenApiReaderImplementation.java create mode 100644 shared/src/main/java/gov/hhs/cdc/trustedintermediary/wrappers/OpenApiReader.java diff --git a/shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/openapi/OpenApiReaderImplementation.java b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/openapi/OpenApiReaderImplementation.java new file mode 100644 index 000000000..c028aeb4d --- /dev/null +++ b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/openapi/OpenApiReaderImplementation.java @@ -0,0 +1,39 @@ +package gov.hhs.cdc.trustedintermediary.external.openapi; + +import gov.hhs.cdc.trustedintermediary.domainconnector.UnableToReadOpenApiSpecificationException; +import gov.hhs.cdc.trustedintermediary.wrappers.OpenApiReader; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +/** + * Basic implementation of a Reader for OpenApi to promote code reuse. If additional functionality + * is needed, consider implementing a library and wrapping it. + */ +public class OpenApiReaderImplementation implements OpenApiReader { + private static final OpenApiReaderImplementation INSTANCE = new OpenApiReaderImplementation(); + + public static OpenApiReaderImplementation getInstance() { + return INSTANCE; + } + + /** + * Loads the stream of an OpenApi file and returns the output as a string. + * + * @param fileName Name of the file to load + * @return File contents as string + * @throws UnableToReadOpenApiSpecificationException If there is an issue loading the Api file + */ + @Override + public String openAsString(String fileName) throws UnableToReadOpenApiSpecificationException { + InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName); + try { + return new String( + Objects.requireNonNull(stream).readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException | NullPointerException e) { + throw new UnableToReadOpenApiSpecificationException( + "Failed to open OpenAPI specification for " + fileName, e); + } + } +} diff --git a/shared/src/main/java/gov/hhs/cdc/trustedintermediary/wrappers/OpenApiReader.java b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/wrappers/OpenApiReader.java new file mode 100644 index 000000000..ac0318876 --- /dev/null +++ b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/wrappers/OpenApiReader.java @@ -0,0 +1,8 @@ +package gov.hhs.cdc.trustedintermediary.wrappers; + +import gov.hhs.cdc.trustedintermediary.domainconnector.UnableToReadOpenApiSpecificationException; + +/** Wrapper for classes that load OpenApi documentation. */ +public interface OpenApiReader { + String openAsString(String fileName) throws UnableToReadOpenApiSpecificationException; +} From 30b0a73fb7a350bb7e43d8d72a59b1bb222549f5 Mon Sep 17 00:00:00 2001 From: Luis Pabon Date: Wed, 17 Jul 2024 14:43:00 -0400 Subject: [PATCH 4/6] Use OpenApiReaderImplementation to reduce duplicate api code --- .../gov/hhs/cdc/trustedintermediary/OpenApi.java | 12 ++---------- .../auth/AuthDomainRegistration.java | 12 ++---------- .../etor/EtorDomainRegistration.java | 16 ++-------------- 3 files changed, 6 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/gov/hhs/cdc/trustedintermediary/OpenApi.java b/app/src/main/java/gov/hhs/cdc/trustedintermediary/OpenApi.java index 8d6197941..4ba9939e0 100644 --- a/app/src/main/java/gov/hhs/cdc/trustedintermediary/OpenApi.java +++ b/app/src/main/java/gov/hhs/cdc/trustedintermediary/OpenApi.java @@ -2,11 +2,9 @@ import gov.hhs.cdc.trustedintermediary.context.ApplicationContext; import gov.hhs.cdc.trustedintermediary.domainconnector.UnableToReadOpenApiSpecificationException; +import gov.hhs.cdc.trustedintermediary.external.openapi.OpenApiReaderImplementation; import gov.hhs.cdc.trustedintermediary.wrappers.YamlCombiner; import gov.hhs.cdc.trustedintermediary.wrappers.YamlCombinerException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.Set; /** Directs the construction of a full YAML OpenAPI specification */ @@ -39,12 +37,6 @@ public String generateApiDocumentation(final Set openApiSpecifications) String getBaselineDocumentation() throws UnableToReadOpenApiSpecificationException { String fileName = "openapi_base.yaml"; - try (InputStream openApiStream = - getClass().getClassLoader().getResourceAsStream(fileName)) { - return new String(openApiStream.readAllBytes(), StandardCharsets.UTF_8); - } catch (IOException e) { - throw new UnableToReadOpenApiSpecificationException( - "Failed to open baseline documentation for " + fileName, e); - } + return OpenApiReaderImplementation.getInstance().openAsString(fileName); } } diff --git a/app/src/main/java/gov/hhs/cdc/trustedintermediary/auth/AuthDomainRegistration.java b/app/src/main/java/gov/hhs/cdc/trustedintermediary/auth/AuthDomainRegistration.java index 75e2492b5..8bc133fca 100644 --- a/app/src/main/java/gov/hhs/cdc/trustedintermediary/auth/AuthDomainRegistration.java +++ b/app/src/main/java/gov/hhs/cdc/trustedintermediary/auth/AuthDomainRegistration.java @@ -7,11 +7,9 @@ import gov.hhs.cdc.trustedintermediary.domainconnector.DomainResponseHelper; import gov.hhs.cdc.trustedintermediary.domainconnector.HttpEndpoint; import gov.hhs.cdc.trustedintermediary.domainconnector.UnableToReadOpenApiSpecificationException; +import gov.hhs.cdc.trustedintermediary.external.openapi.OpenApiReaderImplementation; import gov.hhs.cdc.trustedintermediary.wrappers.InvalidTokenException; import gov.hhs.cdc.trustedintermediary.wrappers.Logger; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.function.Function; import javax.inject.Inject; @@ -43,13 +41,7 @@ public Map> domainRegistra @Override public String openApiSpecification() throws UnableToReadOpenApiSpecificationException { String fileName = "openapi_auth.yaml"; - try (InputStream openApiStream = - getClass().getClassLoader().getResourceAsStream(fileName)) { - return new String(openApiStream.readAllBytes(), StandardCharsets.UTF_8); - } catch (IOException e) { - throw new UnableToReadOpenApiSpecificationException( - "Failed to open OpenAPI specification for " + fileName, e); - } + return OpenApiReaderImplementation.getInstance().openAsString(fileName); } DomainResponse handleAuth(DomainRequest request) { diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java index b888ab4dd..4c4b0c897 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistration.java @@ -39,6 +39,7 @@ import gov.hhs.cdc.trustedintermediary.external.localfile.FileMessageLinkStorage; import gov.hhs.cdc.trustedintermediary.external.localfile.FilePartnerMetadataStorage; import gov.hhs.cdc.trustedintermediary.external.localfile.MockRSEndpointClient; +import gov.hhs.cdc.trustedintermediary.external.openapi.OpenApiReaderImplementation; import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamEndpointClient; import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamOrderSender; import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamResultSender; @@ -46,9 +47,6 @@ import gov.hhs.cdc.trustedintermediary.wrappers.FhirParseException; import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir; import gov.hhs.cdc.trustedintermediary.wrappers.Logger; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -145,17 +143,7 @@ public Map> domainRegistra @Override public String openApiSpecification() throws UnableToReadOpenApiSpecificationException { String fileName = "openapi_etor.yaml"; - try { - return openApiStream(fileName); - } catch (IOException e) { - throw new UnableToReadOpenApiSpecificationException( - "Failed to open OpenAPI specification for " + fileName, e); - } - } - - public String openApiStream(String fileName) throws IOException { - InputStream openApiStream = getClass().getClassLoader().getResourceAsStream(fileName); - return new String(openApiStream.readAllBytes(), StandardCharsets.UTF_8); + return OpenApiReaderImplementation.getInstance().openAsString(fileName); } DomainResponse handleOrders(DomainRequest request) { From 966be3eef6508a459d65779109bcb5232024687f Mon Sep 17 00:00:00 2001 From: Luis Pabon Date: Wed, 17 Jul 2024 14:45:40 -0400 Subject: [PATCH 5/6] Update EtorDomainRegistrationTest.groovy Remove tests that are no longer relevant on the EtorDomainRegistration --- .../etor/EtorDomainRegistrationTest.groovy | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy index 7e669534f..0ef563893 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy @@ -8,7 +8,6 @@ import gov.hhs.cdc.trustedintermediary.domainconnector.DomainRequest import gov.hhs.cdc.trustedintermediary.domainconnector.DomainResponse import gov.hhs.cdc.trustedintermediary.domainconnector.DomainResponseHelper import gov.hhs.cdc.trustedintermediary.domainconnector.HttpEndpoint -import gov.hhs.cdc.trustedintermediary.domainconnector.UnableToReadOpenApiSpecificationException import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.messages.MessageRequestHandler import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata @@ -112,30 +111,6 @@ class EtorDomainRegistrationTest extends Specification { openApiSpecification.contains("paths:") } - def "correctly handles errors when loading OpenAPI"() { - given: - def domainRegistration = Spy(EtorDomainRegistration) - domainRegistration.openApiStream(_ as String) >> { throw new IOException()} - - when: - domainRegistration.openApiSpecification() - - then: - thrown(UnableToReadOpenApiSpecificationException) - } - - def "openApiStream assertion behaves correctly with bad filenames"() { - given: - def domainRegistration = Spy(EtorDomainRegistration) - domainRegistration.openApiStream(_ as String) >> { throw new IOException()} - - when: - domainRegistration.openApiStream("badFile") - - then: - thrown(IOException) - } - def "handleOrders happy path"() { given: def orderMock = new OrderMock("resource id", "a patient ID", "orders", null, null, null, null, null) From 3ae96d20f4bae311fffed1acd3dd597d57dab70d Mon Sep 17 00:00:00 2001 From: Luis Pabon Date: Wed, 17 Jul 2024 16:20:27 -0400 Subject: [PATCH 6/6] Update EtorDomainRegistrationTest.groovy Add test case to cover additional code --- .../etor/EtorDomainRegistrationTest.groovy | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy index 0ef563893..593fd5816 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/EtorDomainRegistrationTest.groovy @@ -10,6 +10,7 @@ import gov.hhs.cdc.trustedintermediary.domainconnector.DomainResponseHelper import gov.hhs.cdc.trustedintermediary.domainconnector.HttpEndpoint import gov.hhs.cdc.trustedintermediary.etor.messages.MessageHdDataType import gov.hhs.cdc.trustedintermediary.etor.messages.MessageRequestHandler +import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataConverter import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataException @@ -455,4 +456,38 @@ class EtorDomainRegistrationTest extends Specification { 1 * mockLogger.logError(_ as String) 1 * requestHandler.handle(null) } + + def "handleMessageRequest logs an error and continues when unable to send message"() { + given: + def expectedStatusCode = 400 + + def request = new DomainRequest(headers: ["recordid": "recordId"]) + def response + + def requestHandler = Mock(MessageRequestHandler) + requestHandler.handle(_ as String) >> { throw new UnableToSendMessageException("DogCow", new NullPointerException()) } + + def connector = new EtorDomainRegistration() + TestApplicationContext.register(EtorDomainRegistration, connector) + + def mockResponseHelper = Mock(DomainResponseHelper) + TestApplicationContext.register(DomainResponseHelper, mockResponseHelper) + + def mockPartnerMetadataOrchestrator = Mock(PartnerMetadataOrchestrator) + TestApplicationContext.register(PartnerMetadataOrchestrator,mockPartnerMetadataOrchestrator) + + def mockLogger = Mock(Logger) + TestApplicationContext.register(Logger, mockLogger) + + TestApplicationContext.injectRegisteredImplementations() + + when: + response = connector.handleMessageRequest(request, requestHandler, _ as String) + + then: + response.statusCode == expectedStatusCode + 1 * mockResponseHelper.constructErrorResponse(expectedStatusCode, _ as Exception) >> new DomainResponse(expectedStatusCode) + 1 * mockLogger.logError(_ as String, _ as Exception) + 1 * mockPartnerMetadataOrchestrator.setMetadataStatusToFailed(_ as String, _ as String) + } }