us.mn.state.health.lims.referral.action.ReferredOutUpdateAction.java Source code

Java tutorial

Introduction

Here is the source code for us.mn.state.health.lims.referral.action.ReferredOutUpdateAction.java

Source

/**
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * The Original Code is OpenELIS code.
 *
 * Copyright (C) CIRG, University of Washington, Seattle WA.  All Rights Reserved.
 *
 */
package us.mn.state.health.lims.referral.action;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.validator.GenericValidator;
import org.apache.struts.Globals;
import org.apache.struts.action.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.hibernate.StaleObjectStateException;
import org.hibernate.Transaction;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import us.mn.state.health.lims.analysis.dao.AnalysisDAO;
import us.mn.state.health.lims.analysis.daoimpl.AnalysisDAOImpl;
import us.mn.state.health.lims.analysis.valueholder.Analysis;
import us.mn.state.health.lims.common.action.BaseAction;
import us.mn.state.health.lims.common.action.IActionConstants;
import us.mn.state.health.lims.common.exception.LIMSRuntimeException;
import us.mn.state.health.lims.common.services.*;
import us.mn.state.health.lims.common.services.StatusService.AnalysisStatus;
import us.mn.state.health.lims.common.services.StatusService.OrderStatus;
import us.mn.state.health.lims.common.util.DateUtil;
import us.mn.state.health.lims.common.util.validator.ActionError;
import us.mn.state.health.lims.hibernate.HibernateUtil;
import us.mn.state.health.lims.note.dao.NoteDAO;
import us.mn.state.health.lims.note.daoimpl.NoteDAOImpl;
import us.mn.state.health.lims.note.valueholder.Note;
import us.mn.state.health.lims.organization.dao.OrganizationDAO;
import us.mn.state.health.lims.organization.daoimpl.OrganizationDAOImpl;
import us.mn.state.health.lims.patient.valueholder.Patient;
import us.mn.state.health.lims.referral.action.beanitems.IReferralResultTest;
import us.mn.state.health.lims.referral.action.beanitems.ReferralItem;
import us.mn.state.health.lims.referral.action.beanitems.ReferredTest;
import us.mn.state.health.lims.referral.dao.ReferralDAO;
import us.mn.state.health.lims.referral.dao.ReferralResultDAO;
import us.mn.state.health.lims.referral.daoimpl.ReferralDAOImpl;
import us.mn.state.health.lims.referral.daoimpl.ReferralResultDAOImpl;
import us.mn.state.health.lims.referral.valueholder.Referral;
import us.mn.state.health.lims.referral.valueholder.ReferralResult;
import us.mn.state.health.lims.result.dao.ResultDAO;
import us.mn.state.health.lims.result.daoimpl.ResultDAOImpl;
import us.mn.state.health.lims.result.valueholder.Result;
import us.mn.state.health.lims.resultlimits.valueholder.ResultLimit;
import us.mn.state.health.lims.sample.dao.SampleDAO;
import us.mn.state.health.lims.sample.daoimpl.SampleDAOImpl;
import us.mn.state.health.lims.sample.valueholder.Sample;
import us.mn.state.health.lims.samplehuman.dao.SampleHumanDAO;
import us.mn.state.health.lims.samplehuman.daoimpl.SampleHumanDAOImpl;
import us.mn.state.health.lims.test.dao.TestDAO;
import us.mn.state.health.lims.test.daoimpl.TestDAOImpl;
import us.mn.state.health.lims.test.valueholder.Test;
import us.mn.state.health.lims.testresult.dao.TestResultDAO;
import us.mn.state.health.lims.testresult.daoimpl.TestResultDAOImpl;
import us.mn.state.health.lims.testresult.valueholder.TestResult;
import us.mn.state.health.lims.typeoftestresult.valueholder.TypeOfTestResult.ResultType;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

public class ReferredOutUpdateAction extends BaseAction {

    private List<ReferralSet> referralSetList;
    private List<ReferralResult> removableReferralResults;
    private List<ReferralItem> modifiedItems;
    private List<ReferralItem> canceledItems;
    private Set<Sample> parentSamples;
    private List<Sample> modifiedSamples;
    private ActionMessages errors;

    private final ReferralDAO referralDAO = new ReferralDAOImpl();
    private final ReferralResultDAO referralResultDAO = new ReferralResultDAOImpl();
    private final OrganizationDAO organizationDAO = new OrganizationDAOImpl();
    private final ResultDAO resultDAO = new ResultDAOImpl();
    private final SampleDAO sampleDAO = new SampleDAOImpl();
    private final AnalysisDAO analysisDAO = new AnalysisDAOImpl();
    private final NoteDAO noteDAO = new NoteDAOImpl();
    private final TestResultDAO testResultDAO = new TestResultDAOImpl();

    private static final String RESULT_SUBJECT = "Result Note";
    private TestDAO testDAO = new TestDAOImpl();
    private SampleHumanDAO sampleHumanDAO = new SampleHumanDAOImpl();

    @Override
    protected String getPageSubtitleKey() {
        return "referral.out.manage";
    }

    @Override
    protected String getPageTitleKey() {
        return "referral.out.manage";
    }

    @SuppressWarnings("unchecked")
    @Override
    protected ActionForward performAction(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        parentSamples = new HashSet<Sample>();
        modifiedSamples = new ArrayList<Sample>();
        errors = new ActionMessages();
        request.getSession().setAttribute(SAVE_DISABLED, TRUE);

        DynaActionForm dynaForm = (DynaActionForm) form;

        List<ReferralItem> referralItems = (List<ReferralItem>) PropertyUtils.getProperty(dynaForm,
                "referralItems");

        selectModifiedAndCanceledItems(referralItems);

        validateModifedItems();

        if (errors.size() > 0) {
            saveErrors(request, errors);
            request.setAttribute(Globals.ERROR_KEY, errors);

            return mapping.findForward(IActionConstants.FWD_VALIDATION_ERROR);
        }

        try {
            createReferralSets();
        } catch (LIMSRuntimeException e) {
            saveErrors(request, errors);
            request.setAttribute(Globals.ERROR_KEY, errors);

            return mapping.findForward(IActionConstants.FWD_VALIDATION_ERROR);
        }

        Transaction tx = HibernateUtil.getSession().beginTransaction();

        try {
            for (ReferralSet referralSet : referralSetList) {
                referralDAO.updateData(referralSet.referral);

                for (ReferralResult referralResult : referralSet.updatableReferralResults) {
                    Result result = referralResult.getResult();
                    if (result != null) {
                        if (result.getId() == null) {
                            resultDAO.insertData(result);
                        } else {
                            result.setSysUserId(currentUserId);
                            resultDAO.updateData(result);
                        }
                    }

                    if (referralResult.getId() == null) {
                        referralResultDAO.insertData(referralResult);
                    } else {
                        referralResultDAO.updateData(referralResult);
                    }
                }

                if (referralSet.note != null) {
                    if (referralSet.note.getId() == null) {
                        noteDAO.insertData(referralSet.note);
                    } else {
                        noteDAO.updateData(referralSet.note);
                    }
                }
            }

            for (ReferralResult referralResult : removableReferralResults) {

                referralResult.setSysUserId(currentUserId);
                referralResultDAO.deleteData(referralResult);

                if (referralResult.getResult() != null && referralResult.getResult().getId() != null) {
                    referralResult.getResult().setSysUserId(currentUserId);
                    resultDAO.deleteData(referralResult.getResult());
                }
            }

            setStatusOfParentSamples();

            for (Sample sample : modifiedSamples) {
                sampleDAO.updateData(sample);
            }

            tx.commit();

        } catch (LIMSRuntimeException lre) {
            tx.rollback();

            ActionError error;
            if (lre.getException() instanceof StaleObjectStateException) {
                error = new ActionError("errors.OptimisticLockException", null, null);
            } else {
                lre.printStackTrace();
                error = new ActionError("error.system", null, null);
            }

            errors.add(ActionMessages.GLOBAL_MESSAGE, error);
            saveErrors(request, errors);
            request.setAttribute(Globals.ERROR_KEY, errors);
            request.setAttribute(ALLOW_EDITS_KEY, "false");
            return mapping.findForward(FWD_FAIL);

        } finally {
            HibernateUtil.closeSession();
        }

        return mapping.findForward(IActionConstants.FWD_SUCCESS);
    }

    private void selectModifiedAndCanceledItems(List<ReferralItem> referralItems) {
        modifiedItems = new ArrayList<ReferralItem>();
        canceledItems = new ArrayList<ReferralItem>();

        for (ReferralItem item : referralItems) {
            if (item.isCanceled()) {
                canceledItems.add(item);
            } else if (item.isModified()) {
                modifiedItems.add(item);
            }
        }
    }

    private void validateModifedItems() {
        for (ReferralItem referralItem : modifiedItems) {
            validateModifedItem(referralItem);
        }
    }

    private void validateModifedItem(ReferralItem referralItem) {
        // if an institution has not been entered then there may not be a test
        if (!institutionEntered(referralItem) && testEntered(referralItem)) {
            ActionError error = new ActionError("error.referral.missingInstitution",
                    referralItem.getAccessionNumber(), null);
            errors.add(ActionErrors.GLOBAL_MESSAGE, error);
        }

        // if a test has not been entered then there can not be a result or
        // report date
        if (!testEntered(referralItem) && (reportDateEntered(referralItem) || resultEntered(referralItem))) {
            ActionError error = new ActionError("error.referral.missingTest", referralItem.getAccessionNumber(),
                    null);
            errors.add(ActionErrors.GLOBAL_MESSAGE, error);
        }

    }

    private boolean institutionEntered(ReferralItem referralItem) {
        return !"0".equals(referralItem.getReferredInstituteId());
    }

    private boolean testEntered(IReferralResultTest resultTest) {
        return !"0".equals(resultTest.getReferredTestId());
    }

    private boolean reportDateEntered(IReferralResultTest resultTest) {
        return !GenericValidator.isBlankOrNull(resultTest.getReferredReportDate());
    }

    private boolean resultEntered(IReferralResultTest resultTest) {
        return !(GenericValidator.isBlankOrNull(resultTest.getReferredResult())
                && "0".equals(resultTest.getReferredDictionaryResult()));
    }

    private void createReferralSets() throws LIMSRuntimeException {
        referralSetList = new ArrayList<ReferralSet>();
        removableReferralResults = new ArrayList<ReferralResult>();

        for (ReferralItem item : canceledItems) {
            referralSetList.add(createCanceledReferralSet(item));
        }

        for (ReferralItem item : modifiedItems) {
            referralSetList.add(createModifiedSet(item));
        }
    }

    private ReferralSet createCanceledReferralSet(ReferralItem item) {
        ReferralSet referralSet = new ReferralSet();

        Referral referral = referralDAO.getReferralById(item.getReferralId());

        referralSet.referral = referral;
        referral.setSysUserId(currentUserId);
        referral.setCanceled(true);

        setStatusForCanceledReferrals(referral);

        return referralSet;
    }

    @SuppressWarnings("unchecked")
    private void setStatusForCanceledReferrals(Referral referral) {

        Analysis analysis = referral.getAnalysis();
        analysis.setReferredOut(false);
        Sample sample = analysis.getSampleItem().getSample();
        parentSamples.add(sample);

    }

    private ReferralSet createModifiedSet(ReferralItem referralItem) throws LIMSRuntimeException {
        // place all existing referral results in list
        ReferralSet referralSet = new ReferralSet();
        referralSet.setExistingReferralResults(
                referralResultDAO.getReferralResultsForReferral(referralItem.getReferralId()));

        Referral referral = referralDAO.getReferralById(referralItem.getReferralId());
        referral.setCanceled(false);
        referral.setSysUserId(currentUserId);
        referral.setOrganization(organizationDAO.getOrganizationById(referralItem.getReferredInstituteId()));
        referral.setSentDate(DateUtil.convertStringDateToTruncatedTimestamp(referralItem.getReferredSendDate()));
        referral.setRequesterName(referralItem.getReferrer());
        referralSet.referral = referral;

        referralSet.note = new NoteService(referral.getAnalysis()).createSavableNote(NoteService.NoteType.INTERNAL,
                referralItem.getNote(), RESULT_SUBJECT, currentUserId);

        createReferralResults(referralItem, referralSet);

        if (referralItem.getAdditionalTests() != null) {
            for (ReferredTest existingAdditionalTest : referralItem.getAdditionalTests()) {
                if (!existingAdditionalTest.isRemove()) {
                    // nothing to do if isRemove, because on insert we reused what we could
                    // then deleted all old referralResults (see below).
                    // removableReferralResults.add(getRemovableReferralableResults(existingAdditionalTest));
                    createReferralResults(existingAdditionalTest, referralSet);
                }
            }
        }

        List<ReferredTest> newAdditionalTests = getNewTests(referralItem.getAdditionalTestsXMLWad());

        for (ReferredTest newReferralTest : newAdditionalTests) {
            newReferralTest.setReferralId(referralItem.getReferralId());
            createReferralResults(newReferralTest, referralSet);
        }

        // any leftovers get deleted
        this.removableReferralResults.addAll(referralSet.getExistingReferralResults());

        return referralSet;
    }

    /**
     * Reuse any existing referrableResults, placing the submitted results in
     * them. Then any remaining referral results are removable.
     ***/
    private void createReferralResults(IReferralResultTest referralItem, ReferralSet referralSet) {
        if (referralItem.getReferredTestIdShadow() != null
                && !referralItem.getReferredTestId().equals(referralItem.getReferredTestIdShadow())) {
            referralSet.updateTest(referralItem.getReferredTestIdShadow(), referralItem.getReferredTestId(),
                    currentUserId);
        } else {
            String referredResultType = getReferredResultType(referralItem, null);
            if (ResultType.isMultiSelectVariant(referredResultType)) {
                if (!GenericValidator.isBlankOrNull(referralItem.getMultiSelectResultValues())
                        && !"{}".equals(referralItem.getMultiSelectResultValues())) {
                    JSONParser parser = new JSONParser();
                    try {
                        JSONObject jsonResult = (JSONObject) parser
                                .parse(referralItem.getMultiSelectResultValues());
                        for (Object key : jsonResult.keySet()) {
                            String[] ids = ((String) jsonResult.get(key)).trim().split(",");
                            //This will populate a result for each item in the multiselect referral result
                            for (String id : ids) {
                                ReferralResult referralResult = referralSet.getNextReferralResult();
                                referralItem.setReferredDictionaryResult(id); // move particular multi result into (single) dictionary result.
                                fillReferralResultResult(referralItem, referralResult,
                                        Integer.parseInt((String) key));
                            }
                        }
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                } else {
                    ReferralResult referralResult = referralSet.getNextReferralResult();
                    fillReferralResultResult(referralItem, referralResult, 0);
                }
            } else {
                ReferralResult referralResult = referralSet.getNextReferralResult();
                fillReferralResultResult(referralItem, referralResult, 0);
            }
        }
    }

    private void fillReferralResultResult(IReferralResultTest referralItem, ReferralResult referralResult,
            int grouping) {
        referralResult.setSysUserId(currentUserId);

        setReferredResultReportDate(referralItem, referralResult);
        setReferredResultTestId(referralItem, referralResult);
        referralResult.setReferralId(referralItem.getReferralId());
        Result result = referralResult.getResult();

        if (result == null && !GenericValidator.isBlankOrNull(referralItem.getReferredResultType())) {
            result = new Result();
        }

        if (result != null) {
            setResultValuesForReferralResult(referralItem, result, grouping);
            referralResult.setResult(result);
        }

    }

    /**
     * If the referredTest.referredResultType is "M" the particular value to
     * translate into the result should already be loaded in
     * referredTest.referredDictionaryResult
     * 
     */
    private void setResultValuesForReferralResult(IReferralResultTest referredTest, Result result, int grouping) {
        result.setSysUserId(currentUserId);
        result.setSortOrder("0");

        Test test = testDAO.getTestById(referredTest.getReferredTestId());
        Sample sample = referralDAO.getReferralById(referredTest.getReferralId()).getAnalysis().getSampleItem()
                .getSample();
        Patient patient = sampleHumanDAO.getPatientForSample(sample);
        ResultLimit limit = new ResultLimitService().getResultLimitForTestAndPatient(test, patient);
        result.setMinNormal(limit != null ? limit.getLowNormal() : 0.0);
        result.setMaxNormal(limit != null ? limit.getHighNormal() : 0.0);
        result.setGrouping(grouping);

        String referredResultType = getReferredResultType(referredTest, test);
        result.setResultType(referredResultType);
        if (ResultType.isDictionaryVariant(referredResultType)) {
            String dicResult = referredTest.getReferredDictionaryResult();
            if (!(GenericValidator.isBlankOrNull(dicResult) || "0".equals(dicResult))) {
                result.setValue(dicResult);
            }
        } else {
            result.setValue(referredTest.getReferredResult());
        }
    }

    private String getReferredResultType(IReferralResultTest referredTest, Test test) {
        //N.B. this should not be corrected here.  It should be done on load
        /* referredTest.getReferredResultType() is not always accurate
         * alpha-numeric and numeric are not differentiated
         */

        String referredResultType = referredTest.getReferredResultType();

        if (!ResultType.isDictionaryVariant(referredResultType) && test != null) {
            @SuppressWarnings("unchecked")
            List<TestResult> testResults = testResultDAO.getAllActiveTestResultsPerTest(test);

            if (!testResults.isEmpty()) {
                referredResultType = testResults.get(0).getTestResultType();
            }
        }

        return referredResultType;
    }

    private void setReferredResultTestId(IReferralResultTest referralTest, ReferralResult referralResult) {
        if (!"0".equals(referralTest.getReferredTestId())) {
            referralResult.setTestId(referralTest.getReferredTestId());
        }
    }

    private void setReferredResultReportDate(IReferralResultTest referralTest, ReferralResult referralResult)
            throws LIMSRuntimeException {

        if (!GenericValidator.isBlankOrNull(referralTest.getReferredReportDate())) {
            try {
                referralResult.setReferralReportDate(
                        DateUtil.convertStringDateToTruncatedTimestamp(referralTest.getReferredReportDate()));
            } catch (LIMSRuntimeException e) {
                ActionError error = new ActionError("errors.date", referralTest.getReferredReportDate(), null);
                errors.add(ActionErrors.GLOBAL_MESSAGE, error);
                throw e;
            }
        }
    }

    @SuppressWarnings("unchecked")
    private List<ReferredTest> getNewTests(String xml) {
        List<ReferredTest> newTestList = new ArrayList<ReferredTest>();

        if (GenericValidator.isBlankOrNull(xml)) {
            return newTestList;
        }

        try {
            Document testsDom = DocumentHelper.parseText(xml);

            for (Iterator<Element> i = testsDom.getRootElement().elementIterator("test"); i.hasNext();) {
                Element testItem = i.next();

                String testId = testItem.attribute("testId").getValue();

                ReferredTest referralTest = new ReferredTest();
                referralTest.setReferredTestId(testId);
                referralTest.setReferredResultType(new TestService(testId).getResultType());
                referralTest.setReferredResult("");
                referralTest.setReferredDictionaryResult("");
                referralTest.setReferredMultiDictionaryResult("");
                referralTest.setReferredReportDate("");

                newTestList.add(referralTest);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
            throw new LIMSRuntimeException(e);
        }

        return newTestList;
    }

    private void setStatusOfParentSamples() {
        for (Sample sample : parentSamples) {
            List<Analysis> analysisList = analysisDAO.getAnalysesBySampleId(sample.getId());

            String finalizedId = StatusService.getInstance().getStatusID(AnalysisStatus.Finalized);
            boolean allAnalysisFinished = true;

            if (analysisList != null) {
                for (Analysis childAnalysis : analysisList) {
                    Referral referral = referralDAO.getReferralByAnalysisId(childAnalysis.getId());
                    List<ReferralResult> referralResultList;

                    if (referral == null || referral.getId() == null) {
                        referralResultList = new ArrayList<ReferralResult>();
                    } else {
                        referralResultList = referralResultDAO.getReferralResultsForReferral(referral.getId());
                    }

                    if (referralResultList.isEmpty()) {
                        if (!finalizedId.equals(childAnalysis.getStatusId())) {
                            allAnalysisFinished = false;
                            break;
                        }
                    } else {
                        for (ReferralResult referralResult : referralResultList) {
                            if (referralResult.getResult() == null
                                    || GenericValidator.isBlankOrNull(referralResult.getResult().getValue())) {
                                if (!(referral.isCanceled() && finalizedId.equals(childAnalysis.getStatusId()))) {
                                    allAnalysisFinished = false;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (allAnalysisFinished) {
                sample.setStatusId(StatusService.getInstance().getStatusID(OrderStatus.Finished));
                sample.setSysUserId(currentUserId);
                modifiedSamples.add(sample);
            }
        }
    }

    static class ReferralSet {
        Referral referral;
        Note note;
        List<ReferralResult> updatableReferralResults = new ArrayList<ReferralResult>();
        private List<ReferralResult> existingReferralResults = new ArrayList<ReferralResult>();

        public List<ReferralResult> getExistingReferralResults() {
            return existingReferralResults;
        }

        public void setExistingReferralResults(List<ReferralResult> existingReferralResults) {
            this.existingReferralResults = existingReferralResults;
        }

        ReferralResult getNextReferralResult() {
            ReferralResult referralResult = existingReferralResults.isEmpty() ? new ReferralResult()
                    : existingReferralResults.remove(0);
            updatableReferralResults.add(referralResult);

            return referralResult;
        }

        public void updateTest(String oldTestId, String newTestId, String currentUserId) {
            ReferralResult updatedReferralResult = null;
            for (ReferralResult referralResult : existingReferralResults) {
                if (referralResult.getTestId().equals(oldTestId)) {
                    Result result = referralResult.getResult();
                    result.setSysUserId(currentUserId);
                    if (updatedReferralResult == null) {
                        referralResult.setTestId(newTestId);
                        referralResult.setSysUserId(currentUserId);
                        result.setResultType(new TestService(newTestId).getResultType());
                        result.setValue("");
                        updatedReferralResult = referralResult;
                        updatableReferralResults.add(referralResult);
                    }
                }
            }
            existingReferralResults.remove(updatedReferralResult);
        }
    }
}