org.iexhub.connectors.XdsB.java Source code

Java tutorial

Introduction

Here is the source code for org.iexhub.connectors.XdsB.java

Source

/*******************************************************************************
 * Copyright (c) 2015, 2016 Substance Abuse and Mental Health Services Administration (SAMHSA)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Eversolve, LLC - initial IExHub implementation for Health Information Exchange (HIE) integration
 *     Anthony Sute, Ioana Singureanu
 *******************************************************************************/
package org.iexhub.connectors;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.iexhub.config.IExHubConfig;
import org.iexhub.exceptions.UnexpectedServerException;
import org.iexhub.services.client.DocumentRegistry_ServiceStub;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.AdhocQueryRequest;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.AdhocQueryResponse;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.AdhocQueryType;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.LongName;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.ResponseOptionType;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.ReturnType_type0;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.SlotType1;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.ValueListType;
import org.iexhub.services.client.DocumentRegistry_ServiceStub.ValueListTypeSequence;
import org.iexhub.services.client.DocumentRepository_ServiceStub;
import org.iexhub.services.client.DocumentRepository_ServiceStub.DocumentRequest_type0;
import org.iexhub.services.client.DocumentRepository_ServiceStub.RetrieveDocumentSetRequest;
import org.iexhub.services.client.DocumentRepository_ServiceStub.RetrieveDocumentSetRequestType;
import org.iexhub.services.client.DocumentRepository_ServiceStub.RetrieveDocumentSetResponse;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.productivity.java.syslog4j.Syslog;
import org.productivity.java.syslog4j.impl.net.tcp.ssl.SSLTCPNetSyslogConfig;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.UUID;

/**
 * XDS.b   Registry
 * ITI-18 Ad-hoc Query
 * ITI-43 Retrieve Document
 * @author A. Sute
 *
 */

public class XdsB {
    public static final int SYSLOG_SERVER_PORT_MIN = 0;
    public static final int SYSLOG_SERVER_PORT_MAX = 65535;
    private static boolean logXdsBRequestMessages = false;
    private static String logOutputPath = "/java/iexhub/logs";
    private static boolean logSyslogAuditMsgsLocally = false;

    private static String keyStoreFile = IExHubConfig.getConfigLocationPath("1264.jks");
    private static String keyStorePwd = "IEXhub";
    private static String cipherSuites = "TLS_RSA_WITH_AES_128_CBC_SHA";
    private static String httpsProtocols = "TLSv1";

    private static String iti18AuditMsgTemplate = null;
    private static String iti43AuditMsgTemplate = null;

    /** Logger */
    public static Logger log = Logger.getLogger(XdsB.class);

    private static DocumentRegistry_ServiceStub registryStub = null;
    private static DocumentRepository_ServiceStub repositoryStub = null;

    private static final SOAPFactory soapFactory = OMAbstractFactory.getSOAP12Factory();

    private static boolean debugSsl = false;

    private static String registryEndpointUri = null;
    private static String repositoryEndpointUri = null;
    private static boolean testMode = false;

    private static SSLTCPNetSyslogConfig sysLogConfig = null;

    /**
     * @param registryEndpointURI
     */
    public static void setRegistryEndpointURI(String registryEndpointURI) {
        if (registryStub != null) {
            registryStub._getServiceClient().getOptions()
                    .setTo(new org.apache.axis2.addressing.EndpointReference(registryEndpointURI));
            XdsB.registryEndpointUri = registryEndpointURI;
        }
    }

    /**
     * @param repositoryEndpointURI
     */
    public static void setRepositoryEndpointURI(String repositoryEndpointURI) {
        if (repositoryStub != null) {
            repositoryStub._getServiceClient().getOptions()
                    .setTo(new org.apache.axis2.addressing.EndpointReference(repositoryEndpointURI));
            XdsB.repositoryEndpointUri = repositoryEndpointURI;
        }
    }

    /**
     * @param registryEndpointURI
     * @param repositoryEndpointURI
     * @throws AxisFault
     * @throws Exception
     */
    public XdsB(String registryEndpointURI, String repositoryEndpointURI) throws AxisFault, Exception {
        this(registryEndpointURI, repositoryEndpointURI, false);
    }

    /**
     * @param registryEndpointURI
     * @param repositoryEndpointURI
     * @param enableTLS
     * @throws AxisFault
     * @throws Exception
     */
    public XdsB(String registryEndpointURI, String repositoryEndpointURI, boolean enableTLS)
            throws AxisFault, Exception {
        XdsB.logSyslogAuditMsgsLocally = IExHubConfig.getProperty("LogSyslogAuditMsgsLocally",
                XdsB.logSyslogAuditMsgsLocally);
        XdsB.logOutputPath = IExHubConfig.getProperty("LogOutputPath", XdsB.logOutputPath);
        XdsB.logXdsBRequestMessages = IExHubConfig.getProperty("LogXdsBRequestMessages",
                XdsB.logXdsBRequestMessages);
        XdsB.debugSsl = IExHubConfig.getProperty("DebugSSL", XdsB.debugSsl);
        XdsB.testMode = IExHubConfig.getProperty("TestMode", XdsB.testMode);
        XdsB.keyStoreFile = IExHubConfig.getProperty("XdsBKeyStoreFile", XdsB.keyStoreFile);
        XdsB.keyStorePwd = IExHubConfig.getProperty("XdsBKeyStorePwd", XdsB.keyStorePwd);
        XdsB.cipherSuites = IExHubConfig.getProperty("XdsBCipherSuites", XdsB.cipherSuites);
        XdsB.httpsProtocols = IExHubConfig.getProperty("XdsBHttpsProtocols", XdsB.httpsProtocols);

        // If endpoint URI's are null, then set to the values in the properties file...
        if (registryEndpointURI == null) {
            registryEndpointURI = IExHubConfig.getProperty("XdsBRegistryEndpointURI");
        }

        if (repositoryEndpointURI == null) {
            repositoryEndpointURI = IExHubConfig.getProperty("XdsBRepositoryEndpointURI");
        }

        XdsB.registryEndpointUri = registryEndpointURI;
        XdsB.repositoryEndpointUri = repositoryEndpointURI;

        // If Syslog server host is specified, then configure...
        iti18AuditMsgTemplate = IExHubConfig.getProperty("Iti18AuditMsgTemplate");
        iti43AuditMsgTemplate = IExHubConfig.getProperty("Iti43AuditMsgTemplate");
        String syslogServerHost = IExHubConfig.getProperty("SyslogServerHost");
        int syslogServerPort = IExHubConfig.getProperty("SyslogServerPort", -1);
        if ((syslogServerHost != null) && (syslogServerHost.length() > 0)
                && (syslogServerPort > SYSLOG_SERVER_PORT_MIN && syslogServerPort <= SYSLOG_SERVER_PORT_MAX)) {
            if ((iti18AuditMsgTemplate == null) || (iti43AuditMsgTemplate == null)) {
                log.error(
                        "ITI-18 audit message template or ITI-43 audit message template not specified in properties file, "
                                + IExHubConfig.CONFIG_FILE);
                throw new UnexpectedServerException(
                        "ITI-18 audit message template or ITI-43 audit message template not specified in properties file, "
                                + IExHubConfig.CONFIG_FILE);
            }

            System.setProperty("https.cipherSuites", cipherSuites);
            System.setProperty("https.protocols", httpsProtocols);

            if (debugSsl) {
                System.setProperty("javax.net.debug", "ssl");
            }

            sysLogConfig = new SSLTCPNetSyslogConfig();
            sysLogConfig.setHost(syslogServerHost);
            sysLogConfig.setPort(syslogServerPort);
            sysLogConfig.setKeyStore(keyStoreFile);
            sysLogConfig.setKeyStorePassword(keyStorePwd);
            sysLogConfig.setTrustStore(keyStoreFile);
            sysLogConfig.setTrustStorePassword(keyStorePwd);
            sysLogConfig.setUseStructuredData(true);
            sysLogConfig.setMaxMessageLength(8192);
            Syslog.createInstance("sslTcp", sysLogConfig);
        }

        try {
            if (registryEndpointURI != null) {
                // Instantiate DocumentRegistry client stub and enable WS-Addressing...
                registryStub = new DocumentRegistry_ServiceStub(registryEndpointURI);
                registryStub._getServiceClient().engageModule("addressing");

                if (enableTLS) {
                    System.setProperty("javax.net.ssl.keyStore", keyStoreFile);
                    System.setProperty("javax.net.ssl.keyStorePassword", keyStorePwd);
                    System.setProperty("javax.net.ssl.trustStore", keyStoreFile);
                    System.setProperty("javax.net.ssl.trustStorePassword", keyStorePwd);
                    System.setProperty("https.cipherSuites", cipherSuites);
                    System.setProperty("https.protocols", httpsProtocols);

                    if (debugSsl) {
                        System.setProperty("javax.net.debug", "ssl");
                    }

                    registryStub._getServiceClient().engageModule("rampart");
                }
            }

            if (repositoryEndpointURI != null) {
                // Instantiate DocumentRepository client stub and enable WS-Addressing and MTOM...
                repositoryStub = new DocumentRepository_ServiceStub(repositoryEndpointURI);
                repositoryStub._getServiceClient().engageModule("addressing");
                repositoryStub._getServiceClient().getOptions().setProperty(Constants.Configuration.ENABLE_MTOM,
                        Constants.VALUE_TRUE);

                if (enableTLS) {
                    System.setProperty("javax.net.ssl.keyStore", keyStoreFile);
                    System.setProperty("javax.net.ssl.keyStorePassword", keyStorePwd);
                    System.setProperty("javax.net.ssl.trustStore", keyStoreFile);
                    System.setProperty("javax.net.ssl.trustStorePassword", keyStorePwd);
                    System.setProperty("https.cipherSuites", cipherSuites);
                    System.setProperty("https.protocols", httpsProtocols);

                    if (debugSsl) {
                        System.setProperty("javax.net.debug", "ssl");
                    }

                    repositoryStub._getServiceClient().engageModule("rampart");
                }
            }

            log.info("XdsB connector successfully initialized, registryEndpointURI=" + registryEndpointURI
                    + ", repositoryEndpointURI=" + repositoryEndpointURI);
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * @param queryText
     * @param patientId
     * @throws IOException
     */
    private void logIti18AuditMsg(String queryText, String patientId) throws IOException {
        String logMsg = FileUtils.readFileToString(new File(iti18AuditMsgTemplate));

        // Substitutions...
        if ((patientId != null) && (patientId.length() > 0)) {
            patientId = patientId.replace("'", "");
            patientId = patientId.replace("&", "&amp;");
        } else {
            patientId = new String("");
        }

        DateTime now = new DateTime(DateTimeZone.UTC);
        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
        logMsg = logMsg.replace("$DateTime$", fmt.print(now));

        logMsg = logMsg.replace("$AltUserId$", "IExHub");

        logMsg = logMsg.replace("$IexhubIpAddress$", InetAddress.getLocalHost().getHostAddress());

        logMsg = logMsg.replace("$IexhubUserId$", "http://" + InetAddress.getLocalHost().getCanonicalHostName());

        logMsg = logMsg.replace("$DestinationIpAddress$", XdsB.registryEndpointUri);

        logMsg = logMsg.replace("$DestinationUserId$", "IExHub");

        // Query text must be Base64 encoded...
        logMsg = logMsg.replace("$RegistryQueryMtom$", Base64.getEncoder().encodeToString(queryText.getBytes()));

        logMsg = logMsg.replace("$PatientId$", patientId);

        if (logSyslogAuditMsgsLocally) {
            log.info(logMsg);
        }

        if ((sysLogConfig == null) || (iti18AuditMsgTemplate == null)) {
            return;
        }

        // Log the syslog message and close connection
        Syslog.getInstance("sslTcp").info(logMsg);
        Syslog.getInstance("sslTcp").flush();
    }

    /**
     * @param documentId
     * @param repositoryUniqueId
     * @param homeCommunityId
     * @param patientId
     * @throws IOException
     */
    private void logIti43AuditMsg(String documentId, String repositoryUniqueId, String homeCommunityId,
            String patientId) throws IOException {
        String logMsg = FileUtils.readFileToString(new File(iti43AuditMsgTemplate));

        // Substitutions...
        if ((patientId != null) && (patientId.length() > 0)) {
            patientId = patientId.replace("'", "");
            patientId = patientId.replace("&", "&amp;");
        } else {
            patientId = new String("");
        }

        DateTime now = new DateTime(DateTimeZone.UTC);
        DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
        logMsg = logMsg.replace("$DateTime$", fmt.print(now));

        logMsg = logMsg.replace("$AltUserId$", "IExHub");

        logMsg = logMsg.replace("$IexhubIpAddress$", InetAddress.getLocalHost().getHostAddress());

        logMsg = logMsg.replace("$IexhubUserId$", "http://" + InetAddress.getLocalHost().getCanonicalHostName());

        logMsg = logMsg.replace("$DestinationIpAddress$", XdsB.registryEndpointUri);

        logMsg = logMsg.replace("$DestinationUserId$", "IExHub");

        // Repository ID text must be Base64 encoded...
        logMsg = logMsg.replace("$RepositoryIdMtom$",
                Base64.getEncoder().encodeToString(repositoryUniqueId.getBytes()));

        logMsg = logMsg.replace("$PatientId$", patientId);

        logMsg = logMsg.replace("$DocumentId$", documentId);

        if (homeCommunityId != null) {
            logMsg = logMsg.replace("$HomeCommunityId$", homeCommunityId);
        } else {
            logMsg = logMsg.replace("$HomeCommunityId$", "");
        }

        if (logSyslogAuditMsgsLocally) {
            log.info(logMsg);
        }

        if ((sysLogConfig == null) || (iti43AuditMsgTemplate == null)) {
            return;
        }

        // Log the syslog message and close connection
        Syslog.getInstance("sslTcp").info(logMsg);
        Syslog.getInstance("sslTcp").flush();
    }

    /**
     * @param patientId
     * @param queryStartDate
     * @param queryEndDate
     * @return
     * @throws Exception
     */
    public AdhocQueryResponse registryStoredQuery(String patientId, String queryStartDate, String queryEndDate)
            throws Exception {
        return registryStoredQuery(patientId, queryStartDate, queryEndDate, null, null);
    }

    /**
     * @param patientId
     * @param queryStartDate
     * @param queryEndDate
     * @return
     * @throws Exception
     */
    public AdhocQueryResponse registryStoredQuery(String patientId, String queryStartDate, String queryEndDate,
            String typeCode) throws Exception {
        return registryStoredQuery(patientId, queryStartDate, queryEndDate, typeCode, null);
    }

    /**
     * @param patientId
     * @param queryStartDate
     * @param queryEndDate
     * @return
     * @throws Exception
     */
    public AdhocQueryResponse registryStoredQuery(String patientId, String queryStartDate, String queryEndDate,
            String typeCode, String documentUniqueId) throws Exception {
        AdhocQueryRequest request = new AdhocQueryRequest();
        AdhocQueryType adhocQuery = new AdhocQueryType();
        SlotType1 slot = null;
        LongName name = null;
        ValueListType valueList = null;
        ValueListTypeSequence[] valueListSequenceArray = null;
        ValueListTypeSequence valueListSequence = null;
        LongName valueName = null;

        if ((patientId != null) && (patientId.length() > 0)) {
            slot = new SlotType1();
            name = new LongName();
            name.setLongName("$XDSDocumentEntryPatientId");
            slot.setName(name);
            valueList = new ValueListType();
            valueListSequenceArray = new ValueListTypeSequence[1];
            valueListSequence = new ValueListTypeSequence();
            valueName = new LongName();
            valueName.setLongName(patientId);
            valueListSequence.setValue(valueName);
            valueListSequenceArray[0] = valueListSequence;
            valueList.setValueListTypeSequence(valueListSequenceArray);
            slot.setValueList(valueList);
            adhocQuery.addSlot(slot);
        }

        slot = new SlotType1();
        name = new LongName();
        name.setLongName("$XDSDocumentEntryStatus");
        slot.setName(name);
        valueList = new ValueListType();
        valueListSequenceArray = new ValueListTypeSequence[1];
        valueListSequence = new ValueListTypeSequence();
        valueName = new LongName();
        valueName.setLongName("('urn:oasis:names:tc:ebxml-regrep:StatusType:Approved')");
        valueListSequence.setValue(valueName);
        valueListSequenceArray[0] = valueListSequence;
        valueList.setValueListTypeSequence(valueListSequenceArray);
        slot.setValueList(valueList);
        adhocQuery.addSlot(slot);

        if (queryStartDate != null) {
            slot = new SlotType1();
            name = new LongName();
            name.setLongName("$XDSDocumentEntryCreationTimeFrom");
            slot.setName(name);
            valueList = new ValueListType();
            valueListSequenceArray = new ValueListTypeSequence[1];
            valueListSequence = new ValueListTypeSequence();
            valueName = new LongName();
            valueName.setLongName(queryStartDate);
            valueListSequence.setValue(valueName);
            valueListSequenceArray[0] = valueListSequence;
            valueList.setValueListTypeSequence(valueListSequenceArray);
            slot.setValueList(valueList);
            adhocQuery.addSlot(slot);
        }

        if (queryEndDate != null) {
            slot = new SlotType1();
            name = new LongName();
            name.setLongName("$XDSDocumentEntryCreationTimeTo");
            slot.setName(name);
            valueList = new ValueListType();
            valueListSequenceArray = new ValueListTypeSequence[1];
            valueListSequence = new ValueListTypeSequence();
            valueName = new LongName();
            valueName.setLongName(queryEndDate);
            valueListSequence.setValue(valueName);
            valueListSequenceArray[0] = valueListSequence;
            valueList.setValueListTypeSequence(valueListSequenceArray);
            slot.setValueList(valueList);
            adhocQuery.addSlot(slot);
        }

        if (typeCode != null) {
            slot = new SlotType1();
            name = new LongName();
            name.setLongName("$XDSDocumentEntryTypeCode");
            slot.setName(name);
            valueList = new ValueListType();
            valueListSequenceArray = new ValueListTypeSequence[1];
            valueListSequence = new ValueListTypeSequence();
            valueName = new LongName();
            valueName.setLongName(typeCode);
            valueListSequence.setValue(valueName);
            valueListSequenceArray[0] = valueListSequence;
            valueList.setValueListTypeSequence(valueListSequenceArray);
            slot.setValueList(valueList);
            adhocQuery.addSlot(slot);
        }

        if (documentUniqueId != null) {
            slot = new SlotType1();
            name = new LongName();
            name.setLongName("$XDSDocumentEntryUniqueId");
            slot.setName(name);
            valueList = new ValueListType();
            valueListSequenceArray = new ValueListTypeSequence[1];
            valueListSequence = new ValueListTypeSequence();
            valueName = new LongName();
            valueName.setLongName(documentUniqueId);
            valueListSequence.setValue(valueName);
            valueListSequenceArray[0] = valueListSequence;
            valueList.setValueListTypeSequence(valueListSequenceArray);
            slot.setValueList(valueList);
            adhocQuery.addSlot(slot);
        }

        try {
            org.apache.axis2.databinding.types.URI id = new org.apache.axis2.databinding.types.URI();
            id.setPath("urn:uuid:14d4debf-8f97-4251-9a74-a90016b0af0d");
            adhocQuery.setId(id);
            request.setAdhocQuery(adhocQuery);

            ResponseOptionType responseOption = new ResponseOptionType();
            responseOption.setReturnComposedObjects(true);
            responseOption.setReturnType(ReturnType_type0.LeafClass);
            request.setResponseOption(responseOption);

            OMElement requestElement = request.getOMElement(AdhocQueryRequest.MY_QNAME, soapFactory);
            String queryText = requestElement.toString();
            logIti18AuditMsg(queryText, patientId);

            if (logXdsBRequestMessages) {
                Files.write(Paths.get(
                        logOutputPath + "/" + UUID.randomUUID().toString() + "_RegistryStoredQueryRequest.xml"),
                        requestElement.toString().getBytes());
            }

            return registryStub.documentRegistry_RegistryStoredQuery(request);
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * @param repositoryUniqueIdVal
     * @param documents
     * @param patientId
     * @return
     * @throws Exception
     */
    public RetrieveDocumentSetResponse retrieveDocumentSet(String repositoryUniqueIdVal,
            HashMap<String, String> documents, String patientId) throws Exception {
        try {
            RetrieveDocumentSetRequestType documentSetRequestType = new RetrieveDocumentSetRequestType();
            RetrieveDocumentSetRequest documentSetRequest = new RetrieveDocumentSetRequest();

            for (String documentId : documents.keySet()) {
                org.iexhub.services.client.DocumentRepository_ServiceStub.LongName homeCommunityId = null;
                DocumentRequest_type0 documentRequest = new DocumentRequest_type0();
                org.iexhub.services.client.DocumentRepository_ServiceStub.LongName repositoryUniqueId = new org.iexhub.services.client.DocumentRepository_ServiceStub.LongName();
                repositoryUniqueId.setLongName(repositoryUniqueIdVal);
                documentRequest.setRepositoryUniqueId(repositoryUniqueId);

                if (documents.get(documentId) != null) {
                    homeCommunityId = new org.iexhub.services.client.DocumentRepository_ServiceStub.LongName();
                    homeCommunityId.setLongName(documents.get(documentId).toString());
                    documentRequest.setHomeCommunityId(homeCommunityId);
                }

                org.iexhub.services.client.DocumentRepository_ServiceStub.LongName documentUniqueId = new org.iexhub.services.client.DocumentRepository_ServiceStub.LongName();
                documentUniqueId.setLongName(documentId);
                documentRequest.setDocumentUniqueId(documentUniqueId);
                documentSetRequestType.addDocumentRequest(documentRequest);

                logIti43AuditMsg(documentId, repositoryUniqueId.getLongName(),
                        (homeCommunityId == null) ? null : homeCommunityId.getLongName(), patientId);
            }

            documentSetRequest.setRetrieveDocumentSetRequest(documentSetRequestType);

            if (logXdsBRequestMessages) {
                OMElement requestElement = documentSetRequest.getOMElement(RetrieveDocumentSetRequest.MY_QNAME,
                        soapFactory);
                Files.write(Paths.get(
                        logOutputPath + "/" + UUID.randomUUID().toString() + "_RetrieveDocumentSetRequest.xml"),
                        requestElement.toString().getBytes());
            }

            return repositoryStub.documentRepository_RetrieveDocumentSet(documentSetRequest);
        } catch (Exception e) {
            throw e;
        }
    }
}