org.oscarehr.research.eaaps.EaapsHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.oscarehr.research.eaaps.EaapsHandler.java

Source

/**
 * Copyright (c) 2001-2002. Department of Family Medicine, McMaster University. All Rights Reserved.
 * This software is published under the GPL GNU General Public License.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * This software was written for the
 * Department of Family Medicine
 * McMaster University
 * Hamilton
 * Ontario, Canada
 */
package org.oscarehr.research.eaaps;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.oscarehr.PMmodule.dao.ProgramDao;
import org.oscarehr.PMmodule.dao.ProviderDao;
import org.oscarehr.PMmodule.model.Program;
import org.oscarehr.casemgmt.model.CaseManagementNote;
import org.oscarehr.casemgmt.model.CaseManagementNoteLink;
import org.oscarehr.casemgmt.service.CaseManagementManager;
import org.oscarehr.common.dao.DemographicDao;
import org.oscarehr.common.dao.ProviderInboxRoutingDao;
import org.oscarehr.common.dao.QueueDocumentLinkDao;
import org.oscarehr.common.dao.SecRoleDao;
import org.oscarehr.common.dao.StudyDataDao;
import org.oscarehr.common.dao.UserDSMessagePrefsDao;
import org.oscarehr.common.model.Demographic;
import org.oscarehr.common.model.Provider;
import org.oscarehr.common.model.SecRole;
import org.oscarehr.common.model.StudyData;
import org.oscarehr.common.model.UserDSMessagePrefs;
import org.oscarehr.util.SpringUtils;

import oscar.dms.EDoc;
import oscar.dms.EDocUtil;
import oscar.log.LogAction;
import oscar.log.LogConst;
import oscar.oscarLab.ca.all.parsers.DefaultGenericHandler;
import oscar.oscarMessenger.data.MsgMessageData;
import oscar.oscarMessenger.data.MsgProviderData;
import oscar.oscarMessenger.util.MsgDemoMap;
import oscar.util.ConversionUtils;
import ca.uhn.hl7v2.HL7Exception;

import com.lowagie.text.pdf.PdfReader;

/**
 * Handler class for uploading eAAPS PDF documents.
 */
public class EaapsHandler extends DefaultGenericHandler
        implements oscar.oscarLab.ca.all.upload.handlers.MessageHandler {

    private static Logger logger = Logger.getLogger(EaapsHandler.class);

    private StudyDataDao studyDataDao = SpringUtils.getBean(StudyDataDao.class);

    private DemographicDao demographicDao = SpringUtils.getBean(DemographicDao.class);

    private QueueDocumentLinkDao queueDocumentLinkDao = SpringUtils.getBean(QueueDocumentLinkDao.class);

    private ProviderDao providerDao = SpringUtils.getBean(ProviderDao.class);

    private ProviderInboxRoutingDao providerInboxRoutingDao = SpringUtils.getBean(ProviderInboxRoutingDao.class);

    private CaseManagementManager caseManagementManager = SpringUtils.getBean(CaseManagementManager.class);

    private UserDSMessagePrefsDao userDsMessagePrefsDao = SpringUtils.getBean(UserDSMessagePrefsDao.class);

    private ProgramDao programDao = SpringUtils.getBean(ProgramDao.class);

    private SecRoleDao secRoleDao = SpringUtils.getBean(SecRoleDao.class);

    @Override
    public void init(String hl7Body) throws HL7Exception {
        if (logger.isInfoEnabled()) {
            logger.info("Started processing of HL7 message.");
        }

        EaapsMessageSupport message = new EaapsMessageSupport();
        try {
            // parse the message
            message.init(hl7Body);
        } catch (HL7Exception e) {
            logger.warn("Unable to parse HL7 message", e);
            throw e;
        }

        if (logger.isInfoEnabled()) {
            logger.info("Parsed HL7 message successfully");
        }

        // save PDF content out of this message
        String fileName = savePdfContent(message);

        // pull demographic information from the message
        String hash = message.getDemographicHash();
        if (logger.isInfoEnabled()) {
            logger.info("Processing hash code " + hash);
        }

        StudyData studyData = studyDataDao.findSingleByContent(hash);
        if (studyData == null) {
            throw new IllegalStateException("Unable to determine demographic info for " + hash);
        }
        Demographic demo = demographicDao.getDemographicById(studyData.getDemographicNo());
        if (demo == null) {
            throw new IllegalStateException("Demographic record is not available for " + hash);
        }
        if (logger.isInfoEnabled()) {
            logger.info("Loaded demographic " + demo.getDemographicNo() + " for hash code " + hash);
        }

        // create edoc
        if (fileName != null) {
            String provider = getProvider(message, studyData, demo);

            String description = "eAAPS Action plan for " + demo.getFormattedName();

            EDoc doc = createEDoc(message, fileName, demo, description);

            // save edoc
            int documentId = saveEDoc(provider, doc);
            if (logger.isInfoEnabled()) {
                logger.info("Saved edoc " + fileName + " for " + demo.getDemographicNo() + " with provider "
                        + provider + " successfully. Doc Id = " + documentId);
            }

            // route document to the provider
            routeDocument(provider, documentId);
            if (logger.isInfoEnabled()) {
                logger.info("Routed doc " + documentId + " to " + provider + " successfully.");
            }

            // and add a case management note so that the AAP can be seen on the eChart
            addCaseManagementNote(demo, description, CaseManagementNoteLink.DOCUMENT, true, provider);
            if (logger.isInfoEnabled()) {
                logger.info("Added case management note successfully.");
            }

            // make sure that notification will be shown for user
            clearNotifications(hash);
            if (logger.isInfoEnabled()) {
                logger.info("Cleared notification settings successfully.");
            }
        }

        String recommendations = message.getRecommendations();
        if (recommendations != null && !recommendations.isEmpty()) {
            String provider = getProvider(message, studyData, demo);
            addCaseManagementNote(demo, recommendations, CaseManagementNoteLink.CASEMGMTNOTE, false, provider);
            if (logger.isInfoEnabled()) {
                logger.info("Added recommendations successfully.");
            }
        } else {
            if (logger.isInfoEnabled()) {
                logger.info("Recommendations are not provided - skipping.");
            }
        }

        // make sure we notify the MRP as well
        notifyProvider(message, demo);
        if (logger.isInfoEnabled()) {
            logger.info("Completed processing of HL7 message.");
        }
    }

    /**
     * Gets provider number to be associated with the file upload. In case provider number is 
     * specified in the message, it's used. Otherwise, most responsible physician is utilized.
     * In case demographic record doesn't have MRP associated with it, the default provider
     * for the study is utilized.
     * 
     * @param message
     *       HL7 message 
     * @param studyData
     *       Study record for the demographic
     * @param demo
     *       Demographic record to be associated with the document
     * @return
     *       Returns the provider ID
     */
    private String getProvider(EaapsMessageSupport message, StudyData studyData, Demographic demo) {
        String provider = message.getOrderingProvider();
        if (provider == null) {
            provider = demo.getProviderNo();
        }

        if (provider == null && studyData != null) {
            provider = studyData.getProviderNo();
        }

        return provider;
    }

    private void notifyProvider(EaapsMessageSupport message, Demographic demo) {
        String providerId = getProvider(message, null, demo);
        if (providerId == null || providerId.isEmpty()) {
            if (logger.isInfoEnabled()) {
                logger.info("MRP ID is not available for " + demo + " - skipping message generation");
            }
        }

        Provider provider = providerDao.getProvider(providerId);
        if (provider == null) {
            if (logger.isInfoEnabled()) {
                logger.info("Can't find MRP record for " + demo + " - skipping message generation");
            }
            return;
        }

        String mrpNote = message.getProviderNote();
        if (mrpNote == null || mrpNote.isEmpty()) {
            if (logger.isInfoEnabled()) {
                logger.info("MRP note content is null for " + demo + "- skipping message generation");
            }
            return;
        }

        if (logger.isInfoEnabled()) {
            logger.info("Notifying MRP " + provider.getProviderNo());
        }

        MsgMessageData messageData = new MsgMessageData();

        String[] providerIds = new String[] { provider.getProviderNo() };
        ArrayList<MsgProviderData> providerListing = messageData.getProviderStructure(providerIds);
        ArrayList<MsgProviderData> remoteProviders = messageData.getRemoteProvidersStructure();

        String sentToWho;
        if (messageData.isLocals()) {
            sentToWho = messageData.createSentToString(providerIds);
        } else {
            sentToWho = "";
        }

        if (messageData.isRemotes()) {
            sentToWho = sentToWho + " " + messageData.getRemoteNames(remoteProviders);
        }

        String subject = "eAAPS: Recommendations ready for " + demo.getFormattedName();
        String userName = "eAAPS";
        String userNo = "N/A";
        String attachment = null;
        String pdfAttachment = null;
        String messageId = messageData.sendMessage2(mrpNote, subject, userName, sentToWho, userNo, providerListing,
                attachment, pdfAttachment);

        if (logger.isInfoEnabled()) {
            logger.info("Created message " + messageId + " for " + provider.getProviderNo() + " successfully");
        }

        MsgDemoMap msgDemoMap = new MsgDemoMap();
        msgDemoMap.linkMsg2Demo(messageId, demo.getDemographicNo().toString());

        if (logger.isInfoEnabled()) {
            logger.info("Linked message " + messageId + " for " + provider.getProviderNo() + " successfully");
        }
    }

    private void clearNotifications(String hash) {
        for (UserDSMessagePrefs pref : userDsMessagePrefsDao.findAllByResourceId(hash)) {
            pref.setArchived(true);

            userDsMessagePrefsDao.merge(pref);
        }
    }

    private void routeDocument(String provider, int documentId) {
        if (provider == null || provider.isEmpty()) {
            logger.info("Provider is not set for " + documentId + ". Not routing");
            return;
        }

        providerInboxRoutingDao.addToProviderInbox(provider, "" + documentId, "DOC");
        queueDocumentLinkDao.addToQueueDocumentLink(1, documentId);
    }

    private int saveEDoc(String provider, EDoc doc) {
        int documentId = 0;
        try {
            String doc_no = EDocUtil.addDocumentSQL(doc);
            documentId = Integer.parseInt(doc_no);
            LogAction.addLog(provider, LogConst.ADD, "eaap", doc_no, "", "", "EaapDocUpload");
        } catch (Exception e) {
            logger.error("Unable to persist document", e);
            throw new RuntimeException("Unable to persist document", e);
        }
        return documentId;
    }

    private EDoc createEDoc(EaapsMessageSupport message, String fileName, Demographic demo, String description) {
        String docType = "consults";
        String docClass = "eaap";
        String docSubClass = "eaap";
        String contentType = "application/pdf";
        String observationDate = ConversionUtils.toDateString(new Date());
        String providerId = getProvider(message, null, demo);
        String docCreator = providerId;
        String responsible = providerId;
        String reviewer = "";
        String reviewDateTime = "";

        String source = "eAAPS";
        String sourceFacility = message.getSourceFacility();
        char status = 'A';
        String module = "demographic";
        String moduleId = "" + demo.getDemographicNo(); // for some reason this refers to the DEMO ID!!!

        EDoc doc = new EDoc();
        doc.setDescription(description);
        doc.setDocClass(docClass);
        doc.setFileName(fileName);
        doc.setCreatorId(docCreator);
        doc.setResponsibleId(responsible);
        doc.setSource(source);
        doc.setStatus(status);
        doc.setObservationDate(observationDate);
        doc.setReviewerId(reviewer);
        doc.setReviewDateTime(reviewDateTime);
        doc.setModule(module);
        doc.setModuleId(moduleId);
        doc.setType(docType);
        doc.setDocPublic("0");
        doc.setDocClass(docClass);
        doc.setDocSubClass(docSubClass);
        doc.setContentType(contentType);
        doc.setSourceFacility(sourceFacility);
        doc.setNumberOfPages(countPages(fileName));
        return doc;
    }

    private int countPages(String fileName) {
        PdfReader reader = null;
        try {
            reader = new PdfReader(EDocUtil.resovePath(fileName));
            return reader.getNumberOfPages();
        } catch (IOException e) {
            logger.debug("Unable to count pages in " + fileName + " due to " + e.getMessage());
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
        return -1;
    }

    private void addCaseManagementNote(Demographic demo, String description, int noteLink, boolean isSigned,
            String providerNumber) {
        CaseManagementNote cmn = new CaseManagementNote();
        cmn.setObservation_date(new Date());
        cmn.setUpdate_date(new Date());
        cmn.setDemographic_no("" + demo.getDemographicNo());
        cmn.setProviderNo(providerNumber);
        cmn.setNote(description);
        cmn.setSigned(isSigned);
        cmn.setSigning_provider_no(providerNumber);
        try {
            String programNumber = getOscarProgramNumber();
            cmn.setProgram_no(programNumber);
        } catch (Exception e) {
            cmn.setProgram_no("");
        }

        SecRole doctorRole = secRoleDao.findByName("doctor");
        cmn.setReporter_caisi_role(doctorRole.getId().toString());

        cmn.setReporter_program_team("0");
        cmn.setPassword("NULL");
        cmn.setLocked(false);
        cmn.setHistory(description);
        cmn.setPosition(0);
        caseManagementManager.saveNoteSimple(cmn);

        // Add a noteLink to casemgmt_note_link
        CaseManagementNoteLink cmnl = new CaseManagementNoteLink();
        cmnl.setTableName(noteLink);
        cmnl.setTableId(Long.parseLong(EDocUtil.getLastDocumentNo()));
        cmnl.setNoteId(Long.parseLong(EDocUtil.getLastNoteId()));

        EDocUtil.addCaseMgmtNoteLink(cmnl);
    }

    private String getOscarProgramNumber() {
        Program program = programDao.getProgramByName("OSCAR");
        if (program != null) {
            return "" + program.getId();
        }
        return "";
    }

    private String savePdfContent(EaapsMessageSupport message) {
        byte[] pdf = message.getPdf();
        String fileName = message.getPdfFileName();

        if (pdf == null || pdf.length <= 0 || fileName == null || fileName.isEmpty()) {
            logger.info("PDF content or file name is empty, not saving");
            return null;
        }

        try {
            EDocUtil.writeDocContent(fileName, pdf);
        } catch (IOException e) {
            throw new RuntimeException("Unable to save file", e);
        }
        return fileName;
    }

    @Override
    public String parse(String serviceName, String fileName, int fileId) {
        String hl7content = null;
        InputStream is = null;
        try {
            is = new BufferedInputStream(new FileInputStream(new File(fileName)));
            hl7content = IOUtils.toString(is);
            init(hl7content);
        } catch (Exception e) {
            logger.error("Unable to process " + fileName + " for " + serviceName, e);

            return null;
        } finally {
            IOUtils.closeQuietly(is);
        }

        return "success";
    }

}