org.oscarehr.web.MisReportUIBean.java Source code

Java tutorial

Introduction

Here is the source code for org.oscarehr.web.MisReportUIBean.java

Source

/**
 *
 * Copyright (c) 2005-2012. Centre for Research on Inner City Health, St. Michael's Hospital, Toronto. 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
 * Centre for Research on Inner City Health, St. Michael's Hospital,
 * Toronto, Ontario, Canada
 */
package org.oscarehr.web;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.oscarehr.PMmodule.dao.AdmissionDao;
import org.oscarehr.PMmodule.dao.ProgramDao;
import org.oscarehr.PMmodule.model.Admission;
import org.oscarehr.PMmodule.model.Program;
import org.oscarehr.casemgmt.dao.CaseManagementNoteDAO;
import org.oscarehr.casemgmt.model.CaseManagementNote;
import org.oscarehr.common.dao.DemographicDao;
import org.oscarehr.common.dao.FunctionalCentreDao;
import org.oscarehr.common.model.Demographic;
import org.oscarehr.common.model.FunctionalCentre;
import org.oscarehr.util.EncounterUtil;
import org.oscarehr.util.LoggedInInfo;
import org.oscarehr.util.MiscUtils;
import org.oscarehr.util.SpringUtils;

import oscar.util.DateUtils;

public final class MisReportUIBean {

    private static Logger logger = MiscUtils.getLogger();

    private FunctionalCentreDao functionalCentreDao = (FunctionalCentreDao) SpringUtils
            .getBean("functionalCentreDao");
    private AdmissionDao admissionDao = (AdmissionDao) SpringUtils.getBean("admissionDao");
    private ProgramDao programDao = (ProgramDao) SpringUtils.getBean("programDao");
    private DemographicDao demographicDao = (DemographicDao) SpringUtils.getBean("demographicDao");
    private CaseManagementNoteDAO caseManagementNoteDAO = (CaseManagementNoteDAO) SpringUtils
            .getBean("CaseManagementNoteDAO");

    private static int ELDERLY_AGE = 65;

    public static class DataRow {
        public int dataReportId;
        public String dataReportDescription;
        public ArrayList<Integer> dataReportResult = new ArrayList<Integer>();

        private DataRow(int dataReportId, String dataReportDescription, int dataReportResult) {
            this.dataReportId = dataReportId;
            this.dataReportDescription = StringEscapeUtils.escapeHtml(dataReportDescription);
            this.dataReportResult.add(dataReportResult);
        }
    }

    private String reportByDescription = null;
    private GregorianCalendar startDate = null;
    private GregorianCalendar endDate = null;
    private List<Program> selectedPrograms = null;
    private List<Admission> admissions = null;
    private ArrayList<DataRow> dataRows = null;
    private ArrayList<String> headerRow = new ArrayList<String>();
    {
        headerRow.add("Id");
        headerRow.add("Description");
        headerRow.add("Results");
    }

    /**
     * End dates should be treated as inclusive.
     */
    public MisReportUIBean(String functionalCentreId, GregorianCalendar startDate, GregorianCalendar endDate) {

        this.startDate = startDate;
        this.endDate = endDate;

        LoggedInInfo loggedInInfo = LoggedInInfo.loggedInInfo.get();
        FunctionalCentre functionalCentre = functionalCentreDao.find(functionalCentreId);
        reportByDescription = StringEscapeUtils
                .escapeHtml(functionalCentre.getAccountId() + ", " + functionalCentre.getDescription());
        selectedPrograms = programDao.getProgramsByFacilityIdAndFunctionalCentreId(
                loggedInInfo.currentFacility.getId(), functionalCentreId);

        populateAdmissions();
        generateDataRows();
    }

    /**
     * End dates should be treated as inclusive.
     */
    public MisReportUIBean(String[] programIds, GregorianCalendar startDate, GregorianCalendar endDate) {

        this.startDate = startDate;
        this.endDate = endDate;

        selectedPrograms = new ArrayList<Program>();
        StringBuilder programNameList = new StringBuilder();
        for (String programIdString : programIds) {
            int programId = Integer.parseInt(programIdString);
            Program program = programDao.getProgram(programId);
            selectedPrograms.add(program);

            if (programNameList.length() > 0)
                programNameList.append(", ");
            programNameList.append(program.getName());
        }
        reportByDescription = StringEscapeUtils.escapeHtml(programNameList.toString());

        populateAdmissions();
        generateDataRows();
    }

    public ArrayList<String> getHeaderRow() {
        return (headerRow);
    }

    public String getReportByDescription() {
        return (reportByDescription);
    }

    public static String getDateRangeForDisplay(GregorianCalendar startDate, GregorianCalendar endDate) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return (StringEscapeUtils.escapeHtml(simpleDateFormat.format(startDate.getTime()) + " to "
                + simpleDateFormat.format(endDate.getTime()) + " (inclusive)"));
    }

    private void populateAdmissions() {

        admissions = new ArrayList<Admission>();

        for (Program program : selectedPrograms) {
            List<Admission> programAdmissions = admissionDao.getAdmissionsByProgramAndDate(program.getId(),
                    startDate.getTime(), endDate.getTime());

            logger.debug("corresponding mis admissions count:" + admissions.size());

            for (Admission admission : programAdmissions) {
                admissions.add(admission);
                logger.debug("valid mis admission, id=" + admission.getId());
            }
        }
    }

    public void generateDataRows() {
        dataRows = new ArrayList<DataRow>();

        addBedProgramInfo(dataRows);

        dataRows.add(getFaceToFace());
        dataRows.add(getPhone());
        dataRows.add(getIndividualsSeen());
        dataRows.add(getTotalIndividualsServed());
    }

    public ArrayList<DataRow> getDataRows() {
        return (dataRows);
    }

    private boolean isProgramType(Integer programId, String programType) {
        for (Program program : selectedPrograms) {
            if (program.getId().equals(programId)) {
                return (programType.equals(program.getType()));
            }
        }

        return (false);
    }

    private void addBedProgramInfo(ArrayList<DataRow> results) {
        // only pertains to bed programs

        int totalDaysElderly = 0;
        int totalDaysAdult = 0;
        int totalNewAdmissionsElderly = 0;
        int totalNewAdmissionsAdult = 0;
        int totalNewDischargeAdult = 0;
        HashSet<Integer> uniqueElderlyClients = new HashSet<Integer>();
        HashSet<Integer> uniqueAdultClients = new HashSet<Integer>();

        for (Admission admission : admissions) {
            if (isProgramType(admission.getProgramId(), Program.BED_TYPE)) {
                int residentDays = calculateResidentDays(admission);
                boolean isNewAdmission = isNewAdmission(admission);

                Demographic demographic = demographicDao.getDemographicById(admission.getClientId());
                Integer age = DateUtils.getAge(demographic.getBirthDay(), endDate);

                if (age != null && age.intValue() >= ELDERLY_AGE) {
                    totalDaysElderly = totalDaysElderly + residentDays;
                    if (isNewAdmission)
                        totalNewAdmissionsElderly++;

                    uniqueElderlyClients.add(admission.getClientId());
                } else {
                    totalDaysAdult = totalDaysAdult + residentDays;
                    if (isNewAdmission)
                        totalNewAdmissionsAdult++;

                    if (isNewDischarge(admission))
                        totalNewDischargeAdult++;

                    uniqueAdultClients.add(admission.getClientId());
                }
            }
        }

        results.add(new DataRow(4034520, "Resident days - Elderly", totalDaysElderly));
        results.add(new DataRow(4034540, "Resident days - Adult", totalDaysAdult));
        results.add(new DataRow(4014520, "New Resident Admission - Elderly", totalNewAdmissionsElderly));
        results.add(new DataRow(4014540, "New Resident Admission - Adult", totalNewAdmissionsAdult));
        results.add(new DataRow(4104540, "New Resident discharged - Adult", totalNewDischargeAdult));
        results.add(new DataRow(4554520, "Unique Individuals Served by FC - Elderly", uniqueElderlyClients.size()));
        results.add(new DataRow(4554540, "Unique Individuals Served by FC - Adult", uniqueAdultClients.size()));
    }

    private boolean isNewAdmission(Admission admission) {
        return (startDate.before(admission.getAdmissionCalendar())
                && endDate.after(admission.getAdmissionCalendar()));
    }

    private boolean isNewDischarge(Admission admission) {
        return (startDate.before(admission.getDischargeCalendar())
                && endDate.after(admission.getDischargeCalendar()));
    }

    private int calculateResidentDays(Admission admission) {
        GregorianCalendar startBound = startDate;
        if (startBound.before(admission.getAdmissionCalendar()))
            startBound = admission.getAdmissionCalendar();

        GregorianCalendar endBound = endDate;
        if (endBound.after(admission.getDischargeCalendar()))
            endBound = admission.getDischargeCalendar();

        return (DateUtils.calculateDayDifference(startBound, endBound));
    }

    private DataRow getFaceToFace() {
        int visitsCount = 0;

        // count face to face notes in the system pertaining to the allowed programs during that time frame.
        for (Program program : selectedPrograms) {
            visitsCount = visitsCount + countFaceToFaceNotesInProgram(program);
        }

        return (new DataRow(4502440, "Visits Face to Face (must have client record)", visitsCount));
    }

    private int countFaceToFaceNotesInProgram(Program program) {
        List<CaseManagementNote> notes = caseManagementNoteDAO.getCaseManagementNoteByProgramIdAndObservationDate(
                program.getId(), startDate.getTime(), endDate.getTime());

        int count = 0;

        for (CaseManagementNote note : notes) {
            if (EncounterUtil.EncounterType.FACE_TO_FACE_WITH_CLIENT.getOldDbValue()
                    .equals(note.getEncounter_type())) {
                // as per request/requirements only count individuals with a client record.
                // I know, this doesn't entirely make sense as a note must have a client record...
                Demographic demographic = demographicDao.getDemographic(note.getDemographic_no());
                if (demographic != null)
                    count++;
            }
        }

        return (count);
    }

    private DataRow getPhone() {
        int visitsCount = 0;

        // count phone notes in the system pertaining to the allowed programs during that time frame.
        for (Program program : selectedPrograms) {
            visitsCount = visitsCount + countPhoneNotesInProgram(program);
        }

        return (new DataRow(4512440, "Visits - Telephone (named and unique anonymous)", visitsCount));
    }

    private int countPhoneNotesInProgram(Program program) {
        List<CaseManagementNote> notes = caseManagementNoteDAO.getCaseManagementNoteByProgramIdAndObservationDate(
                program.getId(), startDate.getTime(), endDate.getTime());

        int count = 0;

        for (CaseManagementNote note : notes) {
            if (EncounterUtil.EncounterType.TELEPHONE_WITH_CLIENT.getOldDbValue()
                    .equals(note.getEncounter_type())) {
                // as per request/requirements only count individuals who are named or are unique anonymous
                Demographic demographic = demographicDao.getDemographic(note.getDemographic_no());
                if (demographic != null) {
                    if (demographic.getAnonymous() == null
                            || Demographic.UNIQUE_ANONYMOUS.equals(demographic.getAnonymous()))
                        count++;
                }
            }
        }

        return (count);
    }

    private DataRow getIndividualsSeen() {
        HashSet<Integer> individuals = new HashSet<Integer>();

        // count face to face individuals in the system pertaining to the allowed programs during that time frame.
        for (Program program : selectedPrograms) {
            addIndividualsSeenInProgram(individuals, program);
        }

        return (new DataRow(4526000,
                "Service Recipients Seen, (anonymous or no client record, excluding unique anonymous)",
                individuals.size()));
    }

    private void addIndividualsSeenInProgram(HashSet<Integer> individuals, Program program) {
        List<CaseManagementNote> notes = caseManagementNoteDAO.getCaseManagementNoteByProgramIdAndObservationDate(
                program.getId(), startDate.getTime(), endDate.getTime());

        for (CaseManagementNote note : notes) {
            if (EncounterUtil.EncounterType.FACE_TO_FACE_WITH_CLIENT.getOldDbValue()
                    .equals(note.getEncounter_type())) {
                // as per request/requirements only count individuals who are anonymous or have no client record, excluding unique_anonymous
                // sorry can only count people who have demographic records.
                Demographic demographic = demographicDao.getDemographic(note.getDemographic_no());
                if (demographic != null && Demographic.ANONYMOUS.equals(demographic.getAnonymous()))
                    individuals.add(demographic.getDemographicNo());
            }
        }
    }

    private DataRow getTotalIndividualsServed() {
        HashSet<Integer> individuals = new HashSet<Integer>();

        // count individuals in the system pertaining to the allowed programs during that time frame.
        for (Program program : selectedPrograms) {
            addIndividualsServedInProgram(individuals, program);
        }

        return (new DataRow(4552440, "Individuals Served, (total clients)", individuals.size()));
    }

    private void addIndividualsServedInProgram(HashSet<Integer> individuals, Program program) {
        List<CaseManagementNote> notes = caseManagementNoteDAO.getCaseManagementNoteByProgramIdAndObservationDate(
                program.getId(), startDate.getTime(), endDate.getTime());

        for (CaseManagementNote note : notes) {
            Demographic demographic = demographicDao.getDemographic(note.getDemographic_no());
            if (demographic != null)
                individuals.add(demographic.getDemographicNo());
        }
    }

    public static MisReportUIBean getSplitProgramReports(String[] programIds, GregorianCalendar startDate,
            GregorianCalendar endDate) {
        ArrayList<MisReportUIBean> misReportBeans = new ArrayList<MisReportUIBean>();
        StringBuilder description = new StringBuilder();
        MisReportUIBean tempMisReportBean = null;

        ArrayList<String> headerRow = new ArrayList<String>();
        headerRow.add("Id");
        headerRow.add("Description");

        for (String programIdString : programIds) {
            tempMisReportBean = new MisReportUIBean(new String[] { programIdString }, startDate, endDate);

            if (description.length() > 0)
                description.append(", ");
            description.append(tempMisReportBean.getReportByDescription());

            headerRow.add(tempMisReportBean.getReportByDescription());

            misReportBeans.add(tempMisReportBean);
        }

        tempMisReportBean.reportByDescription = description.toString();
        tempMisReportBean.dataRows = combineDataSet(misReportBeans);
        tempMisReportBean.headerRow = headerRow;
        return (tempMisReportBean);
    }

    private static ArrayList<DataRow> combineDataSet(ArrayList<MisReportUIBean> misReportBeans) {
        ArrayList<DataRow> combinedData = new ArrayList<DataRow>();

        combineDataIds(combinedData, misReportBeans);
        combineDataResults(combinedData, misReportBeans);

        return (combinedData);
    }

    private static void combineDataIds(ArrayList<DataRow> combinedData, ArrayList<MisReportUIBean> misReportBeans) {
        for (MisReportUIBean misReportUIBean : misReportBeans)
            combineDataIds(combinedData, misReportUIBean);
    }

    private static void combineDataIds(ArrayList<DataRow> combinedData, MisReportUIBean misReportUIBean) {
        for (DataRow beanRow : misReportUIBean.getDataRows()) {
            DataRow dataRow = getDataRowFromId(combinedData, beanRow.dataReportId);
            if (dataRow == null)
                combinedData.add(new DataRow(beanRow.dataReportId, beanRow.dataReportDescription, 0));
        }
    }

    private static DataRow getDataRowFromId(ArrayList<DataRow> combinedData, int dataReportId) {
        for (DataRow dataRow : combinedData) {
            if (dataRow.dataReportId == dataReportId)
                return (dataRow);
        }

        return (null);
    }

    private static void combineDataResults(ArrayList<DataRow> combinedData,
            ArrayList<MisReportUIBean> misReportBeans) {
        for (DataRow dataRow : combinedData) {
            combineDataResultsFromBeans(dataRow, misReportBeans);
        }
    }

    private static void combineDataResultsFromBeans(DataRow combinedDataRow,
            ArrayList<MisReportUIBean> misReportBeans) {
        ArrayList<Integer> tempResults = new ArrayList<Integer>();

        for (MisReportUIBean reportBean : misReportBeans) {
            tempResults.add(getDataResultsFromArrayRows(reportBean.getDataRows(), combinedDataRow.dataReportId));
        }

        combinedDataRow.dataReportResult = tempResults;
    }

    private static Integer getDataResultsFromArrayRows(ArrayList<DataRow> dataRows, int dataReportId) {
        DataRow tempDataRow = getDataRowFromId(dataRows, dataReportId);
        if (tempDataRow == null)
            return (null);
        else
            return (tempDataRow.dataReportResult.get(0));

    }

}