001package ca.cdr.test.app.clients;
002
003import ca.uhn.hl7v2.HL7Exception;
004import ca.uhn.hl7v2.model.Message;
005import ca.uhn.hl7v2.parser.PipeParser;
006import com.google.common.base.Charsets;
007import jakarta.annotation.Nonnull;
008import jakarta.annotation.Nullable;
009import org.apache.commons.lang3.StringUtils;
010import org.apache.commons.lang3.Validate;
011import org.springframework.web.client.RestClient;
012
013import java.util.Base64;
014import java.util.Objects;
015
016import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
017import static org.springframework.http.HttpHeaders.AUTHORIZATION;
018
019/**
020 * A REST client for sending HL7V2 messages to a Smile CDR server.
021 */
022public class HL7V2RestClient {
023        private static final String HL7V2_MEDIA_TYPE = "application/hl7-v2";
024        private final RestClient myRestClient;
025        private final PipeParser myParser;
026
027        /**
028         * Constructor with a pre-configured RestClient.
029         *
030         * @param theRestClient The RestClient to use
031         */
032        HL7V2RestClient(RestClient theRestClient) {
033                myRestClient = theRestClient;
034                myParser = new PipeParser();
035        }
036
037        /**
038         * Build a new HL7V2RestClient with the given base URL, username, and password.
039         *
040         * @param theBaseUrl  The base URL of the HL7V2 endpoint, including port if needed.
041         * @param theUsername The username for authentication (optional)
042         * @param thePassword The password for authentication (optional)
043         * @return A new HL7V2RestClient
044         */
045        public static HL7V2RestClient build(String theBaseUrl, @Nullable String theUsername, @Nullable String thePassword) {
046                RestClient.Builder builder = RestClient.builder()
047                        .baseUrl(theBaseUrl)
048                        .defaultHeader(CONTENT_TYPE, HL7V2_MEDIA_TYPE);
049                if (!StringUtils.isBlank(theUsername) && !StringUtils.isBlank(thePassword)) {
050                        builder.defaultHeader(
051                                AUTHORIZATION,
052                                "Basic "
053                                        + Base64.getEncoder()
054                                        .encodeToString((theUsername + ":" + thePassword).getBytes(Charsets.UTF_8)));
055                }
056                return new HL7V2RestClient(builder.build());
057        }
058
059        /**
060         * Send an HL7V2 message to the server.
061         *
062         * @param theMessage The HL7V2 message to send
063         * @return The response message from the server
064         * @throws HL7Exception If there is an error parsing the response
065         */
066        @Nonnull
067        public Message sendMessage(String theMessage) throws HL7Exception {
068                Validate.notEmpty(theMessage, "Message is required");
069
070                String responseBody = myRestClient
071                        .post()
072                        .body(theMessage)
073                        .retrieve()
074                        .body(String.class);
075
076                return myParser.parse(Objects.requireNonNull(responseBody));
077        }
078
079        /**
080         * Send a pre-parsed HL7V2 message to the server.
081         *
082         * @param theMessage The pre-parsed HL7V2 message to send
083         * @return The response message from the server
084         * @throws HL7Exception If there is an error encoding the message or parsing the response
085         */
086        @Nonnull
087        public Message sendMessage(Message theMessage) throws HL7Exception {
088                Validate.notNull(theMessage, "Message is required");
089                return sendMessage(theMessage.encode());
090        }
091}