Skip to content

Commit

Permalink
SendResultUseCase implementation (#803)
Browse files Browse the repository at this point in the history
* results endpoint skeleton

* Added scheleton for SendResultUseCase

* Reverted change

* result interface (#804)

* Renamed message => messages to follow naming convention

* edit name getUnderlyingOrder to getUnderlyingReslut

* Abstracted ResultSender for more generic MessageSender and added skeleton implementation

* Removed unused ResultConverter

* Added test coverage

* Added java docs

* Added missing java docs

---------

Co-authored-by: jorge Lopez <[email protected]>
Co-authored-by: Jorge Lopez <[email protected]>
  • Loading branch information
3 people authored Jan 25, 2024
1 parent b544090 commit e8941a2
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gov.hhs.cdc.trustedintermediary.etor.messages;

import java.util.Optional;

/** Interface for sending a generic message. */
public interface MessageSender<T> {
Optional<String> send(T message) throws UnableToSendMessageException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package gov.hhs.cdc.trustedintermediary.etor.messages;

/**
* This interface represents a use case for sending a generic message. It provides a method to
* convert and send the message.
*
* @param <T> the type of message to be sent
*/
public interface SendMessageUseCase<T> {

void convertAndSend(final T message, String receivedSubmissionId)
throws UnableToSendMessageException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gov.hhs.cdc.trustedintermediary.etor.messages;

/** This exception is thrown when there is an error sending a message. */
public class UnableToSendMessageException extends Exception {
public UnableToSendMessageException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gov.hhs.cdc.trustedintermediary.etor.results;

/**
* Interface to wrap a third-party lab result class (Ex: Hapi FHIR Bundle)
*
* @param <T> The underlying FHIR lab result type.
*/
public interface Result<T> {
T getUnderlyingResult();

String getFhirResourceId();

String getPatientId();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package gov.hhs.cdc.trustedintermediary.etor.results;

import gov.hhs.cdc.trustedintermediary.etor.messages.MessageSender;
import gov.hhs.cdc.trustedintermediary.etor.messages.SendMessageUseCase;
import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException;
import javax.inject.Inject;

/** Use case for converting and sending a lab result message. */
public class SendResultUseCase implements SendMessageUseCase<Result<?>> {
private static final SendResultUseCase INSTANCE = new SendResultUseCase();
@Inject MessageSender<Result<?>> sender;

private SendResultUseCase() {}

public static SendResultUseCase getInstance() {
return INSTANCE;
}

@Override
public void convertAndSend(Result<?> result, String receivedSubmissionId)
throws UnableToSendMessageException {
sender.send(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package gov.hhs.cdc.trustedintermediary.external.reportstream;

import gov.hhs.cdc.trustedintermediary.etor.messages.MessageSender;
import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException;
import gov.hhs.cdc.trustedintermediary.etor.results.Result;
import java.util.Optional;

/**
* This class is responsible for sending results to the ReportStream service and receiving a
* response back.
*/
public class ReportStreamResultSender implements MessageSender<Result<?>> {

private static final ReportStreamResultSender INSTANCE = new ReportStreamResultSender();

public static ReportStreamResultSender getInstance() {
return INSTANCE;
}

private ReportStreamResultSender() {}

@Override
public Optional<String> send(Result<?> result) throws UnableToSendMessageException {
// todo: implement in #616
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package gov.hhs.cdc.trustedintermediary

import gov.hhs.cdc.trustedintermediary.etor.results.Result

/**
* A mock implementation of the {@link gov.hhs.cdc.trustedintermediary.etor.results.Result} interface that is easy to use in tests.
*/
class ResultMock<T> implements Result<T> {

private String fhirResourceId
private String patientId
private T underlyingResult

ResultMock(String fhirResourceId, String patientId, T underlyingOrders) {
this.fhirResourceId = fhirResourceId
this.patientId = patientId
this.underlyingResult = underlyingOrders
}

@Override
T getUnderlyingResult() {
return underlyingResult
}

@Override
String getFhirResourceId() {
return fhirResourceId
}

@Override
String getPatientId() {
return patientId
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package gov.hhs.cdc.trustedintermediary.etor.messages

import gov.hhs.cdc.trustedintermediary.wrappers.HttpClientException
import spock.lang.Specification

class UnableToSendMessageExceptionTest extends Specification {
def "contructor works"() {

given:
def message = "something blew up!"
def cause = new HttpClientException(message, new IOException())

when:
def exception = new UnableToSendMessageException(message, cause)

then:
exception.getMessage() == message
exception.getCause() == cause
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package gov.hhs.cdc.trustedintermediary.etor.results

import gov.hhs.cdc.trustedintermediary.ResultMock
import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext
import gov.hhs.cdc.trustedintermediary.etor.messages.MessageSender
import gov.hhs.cdc.trustedintermediary.etor.messages.SendMessageUseCase
import gov.hhs.cdc.trustedintermediary.etor.messages.UnableToSendMessageException
import spock.lang.Specification

class SendResultUseCaseTest extends Specification {

def mockSender = Mock(MessageSender)

def setup() {
TestApplicationContext.reset()
TestApplicationContext.init()
TestApplicationContext.register(SendMessageUseCase, SendResultUseCase.getInstance())
TestApplicationContext.register(MessageSender, mockSender)
}

def "convertAndSend works"() {
given:
def mockResult = new ResultMock(null, null, "Mock result")
TestApplicationContext.injectRegisteredImplementations()

when:
SendResultUseCase.getInstance().convertAndSend(mockResult, _ as String)

then:
1 * mockSender.send(mockResult) >> Optional.empty()
noExceptionThrown()
}

def "convertAndSend throws exception when send fails"() {
given:
mockSender.send(_) >> { throw new UnableToSendMessageException("DogCow", new NullPointerException()) }
TestApplicationContext.injectRegisteredImplementations()

when:
SendResultUseCase.getInstance().convertAndSend(Mock(Result), _ as String)

then:
thrown(UnableToSendMessageException)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package gov.hhs.cdc.trustedintermediary.external.reportstream

import gov.hhs.cdc.trustedintermediary.ResultMock
import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext
import gov.hhs.cdc.trustedintermediary.etor.messages.MessageSender
import spock.lang.Specification

class ReportStreamResultSenderTest extends Specification {

def setup() {
TestApplicationContext.reset()
TestApplicationContext.init()
TestApplicationContext.register(MessageSender, ReportStreamResultSender.getInstance())
}

def "send results works"() {
when:
ReportStreamResultSender.getInstance().send(new ResultMock(null, null, "Mock result"))

then:
noExceptionThrown()
}
}

0 comments on commit e8941a2

Please sign in to comment.