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